题目链接:https://acm.hdu.edu.cn/showproblem.php?pid=7055
记
s
u
m
[
a
]
[
i
]
sum[a][i]
sum[a][i]为
1
−
i
,
a
1-i,a
1−i,a字符的个数
原式
∑
c
=
97
122
∑
i
=
1
n
∑
j
=
i
n
s
q
c
(
s
,
i
,
j
,
c
)
=
∑
c
=
97
122
∑
i
=
1
n
∑
j
=
i
n
(
s
u
m
[
c
]
[
j
]
−
s
u
m
[
c
]
[
i
−
1
]
)
2
\sum_{c=97}^{122}\sum_{i=1}^{n}\sum_{j=i}^{n}sqc(s,i,j,c) \\{=\sum_{c=97}^{122}\sum_{i=1}^{n}\sum_{j=i}^{n}{(sum[c][j]-sum[c][i-1])^2}}
∑c=97122∑i=1n∑j=insqc(s,i,j,c)=∑c=97122∑i=1n∑j=in(sum[c][j]−sum[c][i−1])2
=
∑
c
=
97
122
∑
i
=
1
n
∑
j
=
1
n
(
s
u
m
2
[
c
]
[
j
]
−
2
∗
s
u
m
[
c
]
[
j
]
∗
s
u
m
[
c
]
[
i
−
1
]
+
s
u
m
2
[
c
]
[
i
−
1
]
)
{=\sum_{c=97}^{122}\sum_{i=1}^{n}\sum_{j=1}^{n}(sum^2[c][j]-2*sum[c][j]*sum[c][i-1]+sum^2[c][i-1])}
=∑c=97122∑i=1n∑j=1n(sum2[c][j]−2∗sum[c][j]∗sum[c][i−1]+sum2[c][i−1])
=
∑
c
=
97
122
∑
i
=
1
n
∑
j
=
i
n
s
u
m
2
[
c
]
[
j
]
−
2
∗
s
u
m
[
c
]
[
i
−
1
]
∗
∑
j
=
i
n
s
u
m
[
a
]
[
j
]
+
∑
j
=
i
n
s
u
m
2
[
c
]
[
i
−
1
]
{= \sum_{c=97}^{122}\sum_{i=1}^{n}{\sum_{j=i}^{n}sum^2[c][j]-2*sum[c][i-1]*\sum_{j=i}^{n}sum[a][j]+\sum_{j=i}^{n}sum^2[c][i-1]}}
=∑c=97122∑i=1n∑j=insum2[c][j]−2∗sum[c][i−1]∗∑j=insum[a][j]+∑j=insum2[c][i−1]
此时我们可以发现一个
O
(
26
∗
n
)
O(26*n)
O(26∗n)的做法:前缀和记录
s
u
m
[
c
]
[
j
]
,
∑
j
=
1
n
s
u
m
2
[
c
]
[
j
]
,
∑
j
=
1
n
s
u
m
[
c
]
[
i
]
sum[c][j],\sum_{j=1}^nsum^2[c][j],\sum_{j=1}^{n}sum[c][i]
sum[c][j],∑j=1nsum2[c][j],∑j=1nsum[c][i],然后遍历
i
,
c
i,c
i,c
但遗憾的是这个做法会T(不过也有可能是我的写法的锅?)
其实上面方法还可以优化:在一段没有 c c c字符的字符串里, s u m [ c ] [ j ] , ∑ j = 1 n s u m 2 [ c ] [ j ] , ∑ j = i n s u m [ c ] [ i ] sum[c][j],\sum_{j=1}^nsum^2[c][j],\sum_{j=i}^{n}sum[c][i] sum[c][j],∑j=1nsum2[c][j],∑j=insum[c][i]是等差的,公差分别 0 , − s u m 2 [ c ] [ j ] , − s u m [ c ] [ j ] 0,-sum^2[c][j],-sum[c][j] 0,−sum2[c][j],−sum[c][j],这也就代表着我们可以通过等差求和快速求得这段的贡献,当然,解决问题时我们总是取两端都是 c c c的字符的中间部分,这样对每一个 c c c,我们只要进行 2 ∗ c n t c 2*cntc 2∗cntc次计算就可以,也就是说可以大概 O ( 2 n ) O(2n) O(2n)解决
AcCode:
#include <iostream>
#include <algorithm>
#include <stack>
#include <cstdio>
#include <cmath>
#include <string>
#include <set>
#include <map>
#include <vector>
#define int long long
#define eps 0.00000001
#define pint std::pair<int,int>
const int N = 1e5 + 100;
const int mod = 998244353;
int sum[N];
int mul[N];
int rem[N];
int number[N];
char str[N];
std::vector<int> vec[30];
inline int mu(const int& a, const int& b) { return a * b % mod; }
signed main() {
std::ios::sync_with_stdio(false);
int t; std::cin >> t;
while (t--) {
int ans = 0;
std::cin >> (str + 1);
int len = std::strlen(str + 1);
for (int i = 0; i < 26; i++) vec[i].clear();
for (int i = 1; i <= len; i++) {
number[i] = (int)str[i] - 97;
vec[number[i]].push_back(i);
}
for (int a = 0; a < 26; a++) {
sum[0] = rem[0] = mul[0] = 0;
int last = 0;
for (auto& v : vec[a]) sum[v] = sum[last] + 1, last = v;//
sum[len] = sum[last];
last = 0;
for (auto& v : vec[a]) rem[v] = (rem[last] + sum[last] * (v - last - 1) + sum[v]), last = v;
rem[len] = (rem[last] + sum[last] * (len - last));
last = 0;
for (auto& v : vec[a]) mul[v] = (mul[last] + (sum[last] * sum[last] * (v - last - 1)) + sum[v] * sum[v]) % mod, last = v;
mul[len] = (mul[last] + sum[last] * sum[last] * (len - last)) % mod;
last = 0;
for (auto& v : vec[a]) ans = ((mul[len] - mul[v] + sum[v] * sum[v] - 2ll * mu((sum[v] - 1), (rem[len] - rem[v] + sum[v])) + (len - v + 1) * mu((sum[v] - 1), (sum[v] - 1))) % mod + mod + ans) % mod;
vec[a].insert(vec[a].begin(), 0);
for (int i = 1; i < vec[a].size(); i++) {
int l = vec[a][i - 1] + 1;
int r = vec[a][i] - 1;
if (l > r) continue;
int tlen = r - l + 1;
int add1 = mu((mul[len] - mul[l - 1]), tlen) - mu((tlen * tlen - tlen) / 2, mu(sum[l - 1], sum[l - 1]));//第一段
int sub2 = mu(2 * sum[l - 1], mu(tlen, rem[len] - rem[l - 1]) - mu((tlen * tlen - tlen) / 2, sum[l - 1]));//的二段
int add3 = mu(mu(sum[l - 1], sum[l - 1]), ((2 * len - l - r + 2) * tlen) / 2);//第三段
add1 = (add1 % mod + mod) % mod;
sub2 = (sub2 % mod + mod) % mod;
add3 = (add3 % mod + mod) % mod;
ans = ans + add1 - sub2 + add3;
ans = (ans % mod + mod) % mod;
}
}
std::cout << ans % mod << std::endl;
}
}