這個在翁文濤的論文裏有講到c++
大概的就是一個子串的迴文自動機是原串迴文自動機的子圖
因而每隔$\sqrt n$從新跑一個$(k \times \sqrt n,n)$的迴文自動機 記錄迴文串個數和位置 而且分別維護後綴的$fail$和前綴的$fail$spa
每次詢問$(l,r)$只須要把$(k \times\sqrt n,r)$的答案直接加上 再暴力添加$(l,(k \times\sqrt n)-1)$這一段就能夠獲得$ans$了debug
只理解了大概 只能之後遇到題再增強了code
$update:$新寫了一篇$BZOJ5384$的博客,可是用那一題的方法加上主席樹能夠作到更優的複雜度get
#include<bits/stdc++.h> using namespace std; #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);} #define pa pair<int,int> #define mod 1000000007 #define ll long long #define mk make_pair #define pb push_back #define fi first #define se second #define cl(x) memset(x,0,sizeof x) #ifdef Devil_Gary #define bug(x) cout<<(#x)<<" "<<(x)<<endl #define debug(...) fprintf(stderr, __VA_ARGS__) #else #define bug(x) #define debug(...) #endif const int INF = 0x7fffffff; const int N=1e5+5; const int M=355; /* char *TT,*mo,but[(1<<15)+2]; #define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/ inline int read(){ int x=0,rev=0,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return rev?-x:x; } int type,n,S,T,Q,a[N],Ans,id=1; int ans[M][N],p[M][N],pos[M][N]; int pb,pf,c[N][26],qf[N][26],f[N],len[N],vis[N]; char s[N]; void exback(int l,int i){ int x=a[i]; if(i-len[pb]-1<l||a[i-len[pb]-1]!=x) pb=qf[pb][x]; if(!c[pb][x]){ len[++id]=len[pb]+2; int k=f[pb]; if(a[i-len[k]-1]!=x) k=qf[k][x]; k=c[k][x]; memcpy(qf[id],qf[k],sizeof qf[k]); qf[id][a[i-len[k]]]=k,f[id]=k,c[pb][x]=id; } pb=c[pb][x]; if(len[pb]==i-l+1) pf=pb; } void exfront(int i,int r){ int x=a[i]; if(i+len[pf]+1>r||a[i+len[pf]+1]!=x) pf=qf[pf][x]; if(!c[pf][x]){ len[++id]=len[pf]+2; int k=f[pf]; if(a[i+len[k]+1]!=x) k=qf[k][x];k=c[k][x]; memcpy(qf[id],qf[k],sizeof qf[k]); qf[id][a[i+len[k]]]=k,f[id]=k,c[pf][x]=id; } pf=c[pf][x]; if(len[pf]==r-i+1) pb=pf; } int calc(int x){ return (x-1)/S+1; } int main(){ #ifdef Devil_Gary freopen("in.txt","r",stdin); #endif type=read(),n=read(),Q=read(),S=sqrt(n),scanf("%s",s+1); for(int i=1;i<=n;i++) a[i]=s[i]-'a'; f[0]=f[1]=1,len[1]=-1; for(int i=0;i<26;i++) qf[0][i]=1; memset(pos,127/3,sizeof pos); for(int L=1,i=1;L<=n;L+=S,i++){ pb=pf=0,++T; for(int j=L;j<=n;j++){ exback(L,j); ans[i][j]=ans[i][j-1],p[i][j]=pf; if(vis[pb]<T) vis[pb]=T,pos[i][pb]=j,ans[i][j]++; } } while(Q--){ int L=read(),R=read(); if(type) L^=Ans,R^=Ans;Ans=0; if(calc(L)==calc(R)){ pb=0,++T; for(int j=L;j<=R;j++){ exback(L,j); if(vis[pb]<T) ++Ans,vis[pb]=T; } } else{ int i=calc(L);Ans=ans[i+1][R]; pf=p[i+1][R],++T; for(int j=i*S;j>=L;j--){ exfront(j,R); if(vis[pf]<T) vis[pf]=T,Ans+=pos[i+1][pf]>R; } } printf("%d\n",Ans); } }