大致题意
给一个字符串(S),求(S=(AB)^iC)的方案数,其中(F(A)≤F(C)),(F(S))表示字符串 (S) 中出现奇数次的字符的数量
分析
设(cnt_i)表示奇数字符数小于等于(i)的(A)的个数
枚举(AB)的长度,然后用(KMP)的(next)数组去枚举循环次数(i),将小于等于(C)中奇数字符的数量的(A)的方案数,也就是(cnt_{j})((j)为(C)中出现奇数次字符从数量)加到答案中,并更新一下(cnt)
最坏时间复杂度(O(n×(logn+26))),不开(O2) (92)~(96)pts,开(O2)稳过
(code)
/*
xcxc82
*/
#include<bits/stdc++.h>
using namespace std;
const int MAXN = (1<<20)+10;
inline int read(){
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;return ~(X-1);
}
int pre[MAXN],suf[MAXN],next[MAXN],pre_value[30];
int buc[30];
bool vis[30];
int T,n;
long long ans;
string s;
void clear(){
ans = 0;
memset(vis,false,sizeof(vis));
memset(pre,0,sizeof(pre));
memset(suf,0,sizeof(suf));
memset(next,0,sizeof(next));
memset(buc,0,sizeof(buc));
memset(pre_value,0,sizeof(pre_value));
}
void kmp(){
int j = 0;
for(int i=2;i<=n;i++){
while(j>0&&s[i]!=s[j+1]) j = next[j];
if(s[i]==s[j+1]) j++;
next[i] = j;
}
}
signed main(){
T = read();
while(T--){
int cnt = 0;
clear();
cin>>s;
s = ' '+s;
n = s.length()-1;
for(int i=1;i<=n;i++){
if(!vis[s[i]-'a'+1]) vis[s[i]-'a'+1] = 1,cnt++;
}
kmp();
for(int i=1;i<=n;i++){
int now = s[i]-'a'+1;
buc[now]++;
if(buc[now]&1) pre[i] = pre[i-1]+1;
else pre[i] = pre[i-1]-1;
}
memset(buc,0,sizeof(buc));
for(int i=n;i>=1;i--){
int now = s[i]-'a'+1;
buc[now]++;
if(buc[now]&1) suf[i] = suf[i+1]+1;
else suf[i] = suf[i+1]-1;
}
for(int i=1;i<n;i++){
if(i>1){
for(int j=i;j<n;j+=i){
if((i%(j-next[j])==0&&j/(j-next[j])>1)||(j==i))
ans+=(long long)(pre_value[suf[j+1]]);
else break;
}
}
for(int j=pre[i];j<=cnt;j++){
pre_value[j]++;
}
}
printf("%lld
",ans);
}
return 0;
}