题解:P7114 [NOIP2020] 字符串匹配
cppcppcpp3 · · 题解
简单数数题,不需要用到 KMP。
考虑
为了应对
显然一段前缀
容易前缀和递推求出。再记
这样求出所有
时间复杂度
// Problem: P7114 [NOIP2020] 字符串匹配
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P7114
// Memory Limit: 512 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=(1<<20)+5;
const int mod=1e9+123;
int n,base,pw[N],h[N];
ll as;
string s;
int hs(int l,int r){return (h[r]-1ll*h[l-1]*pw[r-l+1]%mod+mod)%mod;}
int p[N],q[N],cnt[26],f[27][N];
void init(){
mt19937 rnd(time(0));
base=rnd()%mod,pw[0]=1;
for(int i=1;i<=N-5;++i) pw[i]=1ll*pw[i-1]*base%mod;
}
void solve(){
cin>>s,n=s.size(),s=" "+s,as=0;
for(int i=1;i<=n;++i) h[i]=(1ll*h[i-1]*base%mod+(int)s[i])%mod;
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;++i){
if(cnt[s[i]-'a']) p[i]=p[i-1]-1;
else p[i]=p[i-1]+1;
cnt[s[i]-'a']^=1;
}
memset(cnt,0,sizeof cnt);
for(int i=n;i;--i){
if(cnt[s[i]-'a']) q[i]=q[i+1]-1;
else q[i]=q[i+1]+1;
cnt[s[i]-'a']^=1;
}
for(int j=0;j<=26;++j) for(int i=2;i<=n;++i) f[j][i]=f[j][i-1]+(p[i-1]<=j);
for(int i=2;i<=n;++i){
int val=hs(1,i);
for(int j=i;j<n;j+=i){
if(hs(j-i+1,j)==val) as+=f[q[j+1]][i];
else break;
}
}
cout<<as<<"\n";
for(int i=1;i<=n;++i) q[i]=0;
}
signed main(){
// freopen("string.in","r",stdin);
// freopen("string.out","w",stdout);
init();
cin.tie(nullptr)->sync_with_stdio(false);
int T;cin>>T;
while(T--) solve();
return 0;
}