题目 | Collapsing Strings
Educational Codeforces Round 159 (Rated for Div. 2)
E. Collapsing Strings
https://codeforces.com/contest/1902/problem/E
2 seconds / 256 megabytes
standard input / standard output
Problem
You are given
Let a collapse
- if
is empty, ; - if
is empty, ; - if the last letter of
is equal to the first letter of , then , where is the substring of from the -th letter to the -th one; - otherwise,
, i. e. the concatenation of two strings.
Calculate
Input
The first line contains a single integer
Each of the next
The total length of the strings doesn't exceed
Output
Print a single integer —
Examples
Input
3
aba
ab
ba
Output
20
Input
5
abab
babx
xab
xba
bab
Output
126
题解
注意到,
我们将最长公共前缀记为
根据上面的式子,将问题变形:
下面的重点就是求出
字典树 (Trie 树) 的原理就是将相同前缀的字符串压缩到一起储存,因此可以用它解决这个问题。但是直接使用是不行的,因为字典树维护的是完整字符串的数量,而不是字符串的前缀的数量。
不过这个问题我们简单修改字典树的代码即可,注意下面代码的增删之处(使用 ++
和 --
标记):
void insert(string &s)
{
int p = 0;
for (int i = 0; i < s.size(); i++)
{
int c = s[i] - 'a';
if (!son[p][c])
son[p][c] = ++idx;
p = son[p][c];
++ cnt[p]++;
}
-- cnt[p]++;
}
另外,由于我们减去的是字符串的每种前缀的数量,因此查询的代码也得进行修改:
int query(string &s)
{
-- int p = 0;
++ int p = 0, res = 0;
for (int i = 0; i < s.size(); i++)
{
int c = s[i] - 'a';
if (!son[p][c])
-- return 0;
++ return res;
p = son[p][c];
++ res += cnt[p];
}
-- return cnt[p];
++ return res;
}
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int MAXN = 1e6 + 10;
int son[MAXN][26], cnt[MAXN], idx;
void insert(string &s)
{
int p = 0;
for (int i = 0; i < s.size(); i++)
{
int c = s[i] - 'a';
if (!son[p][c])
son[p][c] = ++idx;
p = son[p][c];
cnt[p]++;
}
}
int query(string &s)
{
int p = 0, res = 0;
for (int i = 0; i < s.size(); i++)
{
int c = s[i] - 'a';
if (!son[p][c])
return res;
p = son[p][c];
res += cnt[p];
}
return res;
}
void solve()
{
int n;
cin >> n;
vector<string> s(n);
int ans = 0;
for (int i = 0; i < n; i++)
{
cin >> s[i];
ans += s[i].size();
insert(s[i]);
}
ans *= 2 * n;
for (int i = 0; i < n; i++)
{
reverse(s[i].begin(), s[i].end());
ans -= 2 * query(s[i]);
}
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
// cin >> t;
while (t--)
solve();
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi