字符串板子
kmp
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+4; char a[maxn],b[maxn]; int p[maxn]; int main(){ scanf("%s",a+1); scanf("%s",b+1); int n=strlen(a+1),m=strlen(b+1); int j=0; for(int i=2;i<=m;i++) { while(j&&b[j+1]!=b[i]) j=p[j]; if(b[j+1]==b[i]) j++; p[i]=j; } j=0; for(int i=1;i<=n;i++){ while(j&&b[j+1]!=a[i]) j=p[j]; if(b[j+1]==a[i]) j++; if(j==m){ printf("%d\n",i-m+1); } } for(int i=1;i<=m;i++) printf("%d\n",p[i]); }
AC自动机
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+4; int tot=0; struct node{ int fail,next[26],tag; }z[maxn]; inline void insert(char *s){ int len=strlen(s); int now=0; for(int i=0;i<len;i++){ int v=s[i]-'a'; if(!z[now].next[v]) z[now].next[v]=++tot; now=z[now].next[v]; } z[now].tag++; } inline void build_AC(){ queue<int>q; for(int i=0;i<26;i++) { z[z[0].next[i]].fail=0; if(z[0].next[i]) q.push(z[0].next[i]); } while(!q.empty()){ int now=q.front();q.pop(); for(int i=0;i<26;i++){ if(z[now].next[i]){ z[z[now].next[i]].fail=z[z[now].fail].next[i]; q.push(z[now].next[i]); }else{ z[now].next[i]=z[z[now].fail].next[i]; } } } } inline int query(char *s){ int len=strlen(s); int now=0,ans=0; for(int i=0;i<len;i++){ now=z[now].next[s[i]-'a']; ans+=z[now].tag; z[now].tag=0; } return ans; }
后缀数组:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+4; struct node{ int pos,x[2];//pos开始的位置是哪里,x[0]与x[1]存储用来基数排序的两个值 node(){} node(int a,int b,int c){ pos=a;x[1]=b;x[0]=c; } }x[maxn],sw[maxn]; char s[maxn]; int z[maxn],buf[maxn],n,rank[maxn],sa[maxn],height[maxn]; inline void count_sort(int upper){ for(int a=0;a<=1;a++){ memset(buf,0,sizeof(buf)); for(int b=1;b<=n;b++) buf[x[b].x[a]]++; for(int b=1;b<=upper;b++) buf[b]+=buf[b-1]; for(int b=n;b>=1;b--) sw[buf[x[b].x[a]]--]=x[b]; for(int b=1;b<=n;b++) x[b]=sw[b]; } int cnt=1; rank[x[1].pos]=1; for(int a=2;a<=n;a++) { if(x[a].x[0]==x[a-1].x[0]&&x[a].x[1]==x[a-1].x[1]) rank[x[a].pos]=cnt; else rank[x[a].pos]=++cnt; } } inline void calc_sa(){ for(int a=1;a<=n;a++) x[a]=node(a,z[a],0); count_sort(1000000);//得到所有rank1[i] for(int a=1;a<=n;a<<=1){ for(int b=1;b<=n;b++) x[b]=node(b,rank[b],a+b<=n?rank[a+b]:0); count_sort(1000000); }//rank[i]第i个后缀排名第几 for(int a=1;a<=n;a++) sa[rank[a]]=a;//sa[i]排名为i的后缀是第几个后缀 for(int a=1;a<=n;a++) { int l=height[rank[a-1]]; if(l>0) l--; int p=sa[rank[a]-1]; while(a+l<=n&&p+l<=n&&s[a+l]==s[p+l]) l++; height[rank[a]]=l; } } int main(){ scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;i++){ z[i]=s[i]; } calc_sa(); for(int i=1;i<=n;i++)printf("%d ",sa[i]); }
Manacher
#include<iostream> #include<cmath> #include<cstring> #define maxn 51000100 using namespace std; int n,hw[maxn],ans; char a[maxn],s[maxn<<1]; void manacher() { int maxright=0,mid; for(int i=1;i<n;i++) { if(i<maxright) hw[i]=min(hw[(mid<<1)-i],hw[mid]+mid-i); else hw[i]=1; for(;s[i+hw[i]]==s[i-hw[i]];++hw[i]); if(hw[i]+i>maxright) { maxright=hw[i]+i; mid=i; } } } void change() { s[0]=s[1]='#'; for(int i=0;i<n;i++) { s[i*2+2]=a[i]; s[i*2+3]='#'; } n=n*2+2; s[n]=0; } int main() { scanf("%s",a); n=strlen(a); change(); manacher(); ans=1; for(int i=0;i<n;i++) ans=max(ans,hw[i]); printf("%d",ans-1); return 0; }