KMP、AC自动机、后缀数组、后缀自动机、manacher、回文自动机
KMP
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=1e6+10; int len1,len2,nt[maxn]; char s[maxn],c[maxn]; int main() { scanf("%s%s",s+1,c+1); len1=strlen(s+1);s[len1+1]=‘#‘; len2=strlen(c+1);c[len2+1]=‘#‘; int pos; for(int i=2;i<=len2;++i) { pos=nt[i-1]; while(pos&&c[pos+1]!=c[i]) pos=nt[pos]; nt[i]= c[pos+1]==c[i]? pos+1:0; } pos=0; for(int i=1;i<=len1;++i) { while(pos&&c[pos+1]!=s[i]) pos=nt[pos]; if(c[pos+1]==s[i]) pos++; if(pos==len2) printf("%d\n",i-len2+1),pos=nt[pos]; } for(int i=1;i<=len2;++i) printf("%d ",nt[i]); return 0; }
AC自动机(bzoj3530)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long const int maxn=1500+7; const ll mod=1e9+7; int n,m; char s[maxn],d[maxn]; char cc;ll ff; template<typename T>void read(T& aa) { aa=0;ff=1; cc=getchar(); while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar(); if(cc==‘-‘) ff=-1,cc=getchar(); while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); aa*=ff; } void mo(ll &x){if(x>=mod) x-=mod;} int fail[maxn],son[maxn][11],has[maxn],tot; void insert() { int len=strlen(s+1),now=0,x; for(int i=1;i<=len;++i) { x=s[i]-‘0‘; if(!son[now][x]) son[now][x]=++tot; now=son[now][x]; } has[now]=1; } int zz[maxn]; void bld() { int s=1,t=0,x; for(int i=0;i<10;++i) if(son[0][i]) zz[++t]=son[0][i]; while(s<=t) { x=zz[s++]; has[x]|=has[fail[x]]; for(int i=0;i<10;++i) { if(son[x][i]) { fail[son[x][i]]=son[fail[x]][i]; zz[++t]=son[x][i]; } else son[x][i]=son[fail[x]][i]; } } } ll f[maxn][maxn][4]; ll solve(int pos,int len,int p) { if(has[pos]) return 0; if(len>n) return 1; if(~f[pos][len][p]) return f[pos][len][p]; ll rs=0; if(p&2) rs+=solve(pos,len+1,p&2); int l=p>>1,r=(p&1)? (d[len]-‘0‘):9; for(int i=l;i<=r;++i) { rs+=solve(son[pos][i],len+1,(p&1)&(i==d[len]-‘0‘)); mo(rs); } return f[pos][len][p]=rs; } int main() { scanf("%s",d+1); n=strlen(d+1); read(m); for(int i=1;i<=m;++i) { scanf("%s",s+1); insert(); } bld(); memset(f,-1,sizeof(f)); printf("%lld",(solve(0,1,3)-1+mod)%mod); return 0; } /* 20 3 2 3 14 */
后缀数组、manacher(0103练习题T3,和去年省选D2T3很像,但不用本质不同,而且简单很多,用后缀数组和马拉车预处理lcp和以i为开头的回文串(放到树状数组里))
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long const int maxn=16e5+10,INF=0x3f3f3f3f; int n,m,Q,ql,qr;ll totans; char A[maxn],B[maxn],S[2*maxn]; int x[maxn],y[maxn],c[maxn],sa[maxn],h[maxn],rad[maxn]; ll aa;char cc; ll read() { aa=0;cc=getchar(); while(cc<‘0‘||cc>‘9‘) cc=getchar(); while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); return aa; } ll minnum[4*maxn]; void bld(int pos,int l,int r) { if(l==r) { minnum[pos]=h[l]; return; } int mid=(l+r)>>1; bld(pos<<1,l,mid); bld(pos<<1|1,mid+1,r); minnum[pos]=min(minnum[pos<<1],minnum[pos<<1|1]); } ll qmin(int pos,int l,int r) { if(l>=ql&&r<=qr) return minnum[pos]; int mid=(l+r)>>1;ll rs=INF; if(ql<=mid) rs=min(rs,qmin(pos<<1,l,mid)); if(qr>mid) rs=min(rs,qmin(pos<<1|1,mid+1,r)); return rs; } ll tot[2][maxn],sum[2][maxn]; ll q(int pos,ll *sz) { ll rs=0; while(pos) { rs+=sz[pos]; pos-=pos&-pos; } return rs; } void chge(int pos,int x,ll *sz,int n) { while(pos<=n) { sz[pos]+=x; pos+=pos&-pos; } } void get_sa(char *s,int n) { int m=‘z‘+1,p; for(int i=0;i<n;++i) c[x[i]=s[i]]++; for(int i=1;i<m;++i) c[i]+=c[i-1]; for(int i=n-1;i>=0;--i) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1) { p=0; for(int i=n-1;i>=n-k;--i) y[p++]=i; for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;++i) c[i]=0; for(int i=0;i<n;++i) c[x[y[i]]]++; for(int i=1;i<m;++i) c[i]+=c[i-1]; for(int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i]; swap(x,y);p=1; x[sa[0]]=0; for(int i=1;i<n;++i) x[sa[i]]= y[sa[i]]==y[sa[i-1]]&& ((sa[i]+k<n&&sa[i-1]+k<n&&y[sa[i]+k]==y[sa[i-1]+k])||(sa[i]+k>=n&&sa[i-1]+k>=n))? p-1:p++; if(p>=n) break; else m=p; } p=0;int u; for(int i=0;i<n;++i) { if(!x[i]) continue; u=sa[x[i]-1]; if(p) p--; while(s[u+p]==s[i+p]) p++; h[x[i]]=p; } memset(minnum,0x3f3f3f3f,sizeof(minnum)); bld(1,1,n-1); } void manacher(char *s,ll *sz,int len,int o) { int maxpos=0,p=0; for(int i=len;i;--i) {//不是从0开始而是从1开始 s[i<<1]=s[i]; s[i<<1|1]=‘#‘; } s[0]=s[1]=‘#‘; for(int i=2;i<=2*len;++i) { if(maxpos>i) rad[i]=min(maxpos-i,rad[2*p-i]); else rad[i]=0; while(i-rad[i]>0&&i+rad[i]<=2*len+1&&s[i-rad[i]]==s[i+rad[i]]) rad[i]++; rad[i]--; if(i+rad[i]>maxpos) p=i,maxpos=i+rad[i]; } for(int i=2;i<=2*len;++i) { chge((i-rad[i]+1)>>1,1,tot[o],len); chge((i+2)>>1,-1,tot[o],len); } } int main() { freopen("palindrome.in","r",stdin); freopen("palindrome.out","w",stdout); scanf("%s",A+1); scanf("%s%s",A+1,B+1); n=strlen(A+1); m=strlen(B+1); for(int i=1;i<=m/2;++i) swap(B[i],B[m-i+1]); for(int i=1;i<=n;++i) S[i-1]=A[i]; S[n]=‘#‘;//n不是n+1 for(int i=1;i<=m;++i) S[i+n]=B[i]; get_sa(S,n+m+1); manacher(A,tot[0],n,0); manacher(B,tot[1],m,1); for(int i=1;i<=n;++i) chge(i,q(i,tot[0]),sum[0],n+1); for(int i=1;i<=m;++i) chge(i,q(i,tot[1]),sum[1],m+1); //注意是n+1和m+1,因为可能询问到 Q=read();int xx,yy,len; for(int i=1;i<=Q;++i) { xx=read(); yy=read(); ql=x[xx-1]; qr=x[yy+n]; if(qr<ql) swap(ql,qr); ++ql; len=qmin(1,1,n+m); totans=len; totans+=q(xx+len,sum[0])-q(xx,sum[0]); totans+=q(yy+len,sum[1])-q(yy,sum[1]);//注意边界 printf("%lld\n",totans); } fclose(stdin);fclose(stdout); return 0; } /* orzAchen babaabbba baaabbb 1 9 6 */
后缀自动机(bzoj2555 LCT+SAM)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; #define ll long long #define lc son[pos][0] #define rc son[pos][1] const int maxn=1200000+7; int mask,n,m,ans; char s[maxn]; string chars; char cc;ll ff; template<typename T>void read(T& aa) { aa=0;ff=1; cc=getchar(); while(cc!=‘-‘&&(cc<‘0‘||cc>‘9‘)) cc=getchar(); if(cc==‘-‘) ff=-1,cc=getchar(); while(cc>=‘0‘&&cc<=‘9‘) aa=aa*10+cc-‘0‘,cc=getchar(); aa*=ff; } void gets(int mask) { scanf("%s",s); chars=s; int len=chars.length(); for(int j=0;j<len;j++) { mask=(mask*131+j)%len; char t=chars[j]; chars[j]=chars[mask]; chars[mask]=t; } } struct Lct{ int fa[maxn],son[maxn][2],w[maxn],laz[maxn],zz[maxn],t; void pd(int pos) { if(!laz[pos]) return; if(lc) laz[lc]+=laz[pos],w[lc]+=laz[pos]; if(rc) laz[rc]+=laz[pos],w[rc]+=laz[pos]; laz[pos]=0; } bool isroot(int pos) { return son[fa[pos]][0]!=pos&&son[fa[pos]][1]!=pos; } void rotate(int pos) { int x,y,p,t; y=fa[x=fa[pos]];t=isroot(x); p=son[x][1]==pos; son[x][p]=son[pos][!p]; fa[son[pos][!p]]=x; son[pos][!p]=x; fa[x]=pos; fa[pos]=y; if(!t) son[y][son[y][1]==x]=pos; } void splay(int pos) { t=0; int x,y; for(x=pos;!isroot(x);x=fa[x]) zz[++t]=x; zz[++t]=x; while(t) pd(zz[t--]); for(;!isroot(pos);rotate(pos)) { y=fa[x=fa[pos]]; if(!isroot(x)) (son[x][1]==pos)^(son[y][1]==x)? rotate(pos):rotate(x); } } void access(int pos) { for(int t=0;pos;pos=fa[pos]) { splay(pos);rc=t; t=pos; } } void lk(int x,int f) { fa[x]=f; access(f); splay(f); if(f) laz[f]+=w[x],w[f]+=w[x]; } void cut(int pos) { access(pos);splay(pos); if(lc) laz[lc]-=w[pos],w[lc]-=w[pos]; fa[lc]=0; lc=0; } }lct; struct Sam{ Sam* next[27],*par; int step; }pool[2*maxn],*root,*last; int tot; Sam* newnode(int step) { Sam *t=pool+(tot++); t->step=step; t->par=NULL; memset(t->next,0,sizeof(t->next)); return t; } void Extend(int w) { // cout<<"Extend"<<w<<": "; Sam *p=last; Sam *np=newnode(p->step+1);lct.w[tot]=1; int x,y; for(;p&&!p->next[w];p=p->par) p->next[w]=np; if(!p) { np->par=root; // cout<<"np link->root\n"; lct.lk(tot,1); } else { Sam *q=p->next[w];x=q-pool+1; if(q->step==p->step+1) { np->par=q; // cout<<"np link->q\n"; lct.lk(tot,x); } else { Sam *nq=newnode(p->step+1);lct.w[tot]=0; memcpy(nq->next,q->next,sizeof(q->next)); y=q->par-pool+1; lct.cut(x); nq->par=q->par; q->par=nq; lct.lk(x,tot); np->par=nq;lct.lk(tot-1,tot); lct.lk(tot,y); // cout<<"nq linked by q&np\n"; for(;p&&p->next[w]==q;p=p->par) p->next[w]=nq; } } last=np; } void add() { gets(mask); int len=chars.length(); for(int i=0;i<len;i++) Extend(chars[i]-‘A‘); } int q(){ gets(mask);int x; int len=chars.length();Sam *now=root; for(int i=0;i<len;i++) if(!(now=now->next[chars[i]-‘A‘])) return 0; lct.splay(x=now-pool+1); return lct.w[x]; } int main() { read(m); scanf("%s",s+1); n=strlen(s+1); last=root=newnode(0); for(int i=1;i<=n;++i) Extend(s[i]-‘A‘); for(int i=1;i<=m;++i) { scanf("%s",s); if(s[0]==‘A‘) add(); else { ans=q(); printf("%d\n",ans); mask^=ans; } } return 0; } /* 4 A ADD BBABBBBAAB QUERY ABA ADD BBABAB QUERY BAAB */
回文自动机留坑