[NOIP2020] 字符串匹配
[NOIP2020] 字符串匹配
首先,可以把
那么就可以枚举出所有长度下的
那么查询有多少个前缀串
枚举这个
然后求有多少个
(
树状数组维护的是字符集大小,所以最后复杂度就是
#include <bits/stdc++.h>
#define ull unsigned long long
void Freopen() {
freopen("", "r", stdin);
freopen("", "w", stdout);
}
using namespace std;
const int N = 1.1e6 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;
int pF[N], sF[N];
int cnt[26], vis[26];
char s[N];
int n;
int tr[N];
void add( int x) {
for (; x <= 27; x += (x & -x)) tr[x] += 1;
}
int ask( int x, int res = 0) {
for (; x; x -= (x & -x)) res += tr[x];
return res;
}
ull hsh[N], pw[N], base = 133337;
ull query( int l, int r) {
return hsh[r] - hsh[l - 1] * pw[r - l + 1];
}
void solve() {
cin >> (s + 1);
n = strlen(s + 1);
for ( int i = 1; i <= n; i ++) hsh[i] = hsh[i - 1] * base + s[i];
for ( int i = 0; i <= n + 1; i ++) tr[i] = pF[i] = sF[i] = 0;
memset(cnt, 0, sizeof cnt);
for ( int i = 1; i <= n; i ++) {
cnt[s[i] - 'a'] ++;
if (cnt[s[i] - 'a'] & 1) pF[i] = pF[i - 1] + 1;
else pF[i] = pF[i - 1] - 1;
}
memset(cnt, 0, sizeof cnt);
for ( int i = n; i; i --) {
cnt[s[i] - 'a'] ++;
if (cnt[s[i] - 'a'] & 1) sF[i] = sF[i + 1] + 1;
else sF[i] = sF[i + 1] - 1;
}
ull ans = 0;
for ( int len = 1; len <= n; len ++) {
int l = 1, r = 1 + len - 1;
ull hs = query(l, r);
while (r <= n && query(l, r) == hs) {
if (r < n) ans += ask(sF[r + 1] + 1);
l += len, r += len;
}
add(pF[len] + 1);
}
cout << ans << '\n';
}
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t;
pw[0] = 1;
for ( int i = 1; i < N; i ++) pw[i] = pw[i - 1] * base;
for (cin >> t; t; t --) solve();
}