字符串算法模板
1.KMP
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> #include<iostream> using namespace std; int next[100]; char p[1000]; int makenext(char p[],int next[]) { int n=strlen(p); for(int i=1,k=0;i<=n;i++) { while(k>0&&p[i]!=p[k]) k=next[k-1]; if(p[i]==p[k]) k++; next[i]=k; } } int kmp(char p[],char t[],int next[]) { int n=strlen(p); int m=strlen(t); makenext(p,next); for(int i=0,k=0;i<m;i++) { while(k>0&&t[i]!=p[k]) k=next[k-1]; if(t[i]==p[k]) k++; if(k==n) return 1; } } int main() { return 0; }
2.AC自动机
//Twenty #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; int ans,t,n; char ch[1000001]; struct node{ node* fail,*s[26]; int w; node(){ fail=NULL;w=0; for(int i=0;i<26;i++) s[i]=NULL; } }*head,*tep,*root; void build(){ root=head; for(int i=0;ch[i]!='\0';i++){ if(root->s[ch[i]-'a']==NULL){ tep=new node(); root->s[ch[i]-'a']=tep; } root=root->s[ch[i]-'a']; } root->w ++; } queue<node*>que; void getfail(){ while(!que.empty()){que.pop();} que.push(head); while(!que.empty()){ root=que.front();que.pop(); for(int i=0;i<26;i++){ if(root->s[i]!=NULL){ if(root==head) root->s[i]->fail=head; else{ tep=root->fail; while(tep){ if(tep->s[i]!=NULL){ root->s[i]->fail=tep->s[i]; break; } tep=tep->fail; } if(!tep) root->s[i]->fail=head; } que.push(root->s[i]); } } } } void query(){ root=head; for(int i=0;ch[i]!='\0';i++){ int h=ch[i]-'a'; while(root->s[h]==NULL&&root->fail!=NULL) root=root->fail ; if(root->s[h]!=NULL){ root=root->s[h]; tep=root; while(tep&&tep->w >0){ ans+=tep->w; tep->w =0; tep=tep->fail; } } } } int main(){ scanf("%d",&t); while(t--){ head=new node(); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",ch); build(); } getfail(); scanf("%s",ch); ans=0; query(); printf("%d\n",ans); } return 0; }
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> #include<stack> const int maxn=1e6+29; using namespace std; int tot,cs,a,ans,n,an[150]; char s[maxn],ch[200][100]; struct node{ node *s[26],*fail,*last; int w,o,id; node(){ for(int i=0;i<26;i++) s[i]=NULL; fail=NULL; w=0; o=0; id=0; last=NULL; } }*root,*tep,*now; void insert(int x){ now=root; for(int i=0;ch[x][i]!='\0';i++){ a=ch[x][i]-'a'; if(!now->s[a]){ tep=new node(); now->s[a]=tep; } now=now->s[a]; } now->w++; now->id=x; } stack<node*>sta; void get_fail(){ queue<node*>que; que.push(root); while(!que.empty() ){ now=que.front(); que.pop() ; sta.push(now); for(int i=0;i<26;i++) if(now->s[i]!=NULL){ if(now==root) now->s[i]->fail=root; else{ tep=now->fail; while(tep->fail&&tep->s[i]==NULL) tep=tep->fail; if(tep->s[i]!=NULL) now->s[i]->fail=tep->s[i]; else now->s[i]->fail=root; } que.push(now->s[i]); } } } void query(){ now=root; for(int i=0;s[i]!='\0';i++){ a=s[i]-'a'; while(now->s[a]==NULL&&now->fail!=NULL ) now=now->fail; if(now->s[a]!=NULL){ now=now->s[a]; now->o++; } } } /*void dfs(node *x){ for(int i=0;i<26;i++) if(x->s[i]!=NULL) dfs(x->s[i]); if(x->w>0&&x->o==tot){ an[++cs]=x->id; } else if(x->w>0&&x->o>tot){ cs=0; tot=x->o; an[++cs]=x->id; } if(x->fail!=NULL) x->fail->o+=x->o; }*/ void cul(){ while(!sta.empty()){ node *x=sta.top(); sta.pop(); for(int i=0;i<26;i++) if(x->s[i]!=NULL){ if(x->s[i]->w>0&&x->s[i]->o==tot){ an[++cs]=x->s[i]->id; } else if(x->s[i]->w>0&&x->s[i]->o>tot){ cs=0; tot=x->s[i]->o; an[++cs]=x->s[i]->id; } if(x->s[i]->fail!=NULL) x->s[i]->fail->o+=x->o; } } } int main() { while(scanf("%d",&n)){ if(n==0) break; cs=0;tot=0; root=new node(); for(int i=1;i<=n;i++){ scanf("%s",ch[i]); insert(i); } get_fail(); scanf("%s",s); query(); //dfs(root); cul(); sort(an+1,an+cs+1); //printf("【\n"); printf("%d\n",tot); for(int i=1;i<=cs;i++) { for(int j=0;ch[an[i]][j]!='\0';j++) printf("%c",ch[an[i]][j]); printf("\n"); }//printf("】\n"); } return 0; }
//Twenty #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int maxn=1e6+299; int u,ans,t,n,root,now,tep,tot,ch[maxn][26],fail[maxn],v[maxn]; char s[maxn]; void build() { now=root; for(int i=0;s[i]!='\0';i++) { int c=s[i]-'a'; if(!ch[now][c]) ch[now][c]=++tot; now=ch[now][c]; } v[now]++; } void get_fail() { queue<int>que; que.push(root); while(!que.empty()) { now=que.front() ; que.pop() ; for(int i=0;i<26;i++) if(u=ch[now][i]) { if(now==root) fail[u]=root; else { tep=fail[now]; while(!ch[tep][i]&&fail[tep]) tep=fail[tep]; if(ch[tep][i]) fail[u]=ch[tep][i]; else fail[u]=root; } que.push(u); } } } void query() { now=root; for(int i=0;s[i]!='\0';i++) { int c=s[i]-'a'; while(fail[now]&&!ch[now][c]) now=fail[now]; if(ch[now][c]) now=ch[now][c]; ans+=v[now]; v[now]=0; tep=fail[now]; while(tep&&v[tep]) { ans+=v[tep]; v[tep]=0; tep=fail[tep]; } } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s); build(); } get_fail(); scanf("%s",s); ans=0; query(); printf("%d\n",ans); return 0; }
3.Manacher
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn=110005; char s[maxn],ss[maxn*2+50]; int ans,n,nn,rad[maxn*20+50]; void work(){ ans=0; for(int i=1,j=0,k;i<nn;){ while(ss[i-j-1]==ss[i+j+1]) j++; rad[i]=j; ans=max(ans,rad[i]); for(k=1;k<=j&&rad[i]-k!=rad[i-k];k++) { rad[i+k]=min(rad[i]-k,rad[i-k]); } i+=k; j=max(j-k,0); } } int main() { while(~scanf("%s",s)){ n=strlen(s); ss[nn++]='*'; ss[nn++]='#'; for(int i=0;i<n;i++){ ss[nn++]=s[i]; ss[nn++]='#'; } ss[nn++]='&'; work(); printf("%d\n",ans); nn=0; } return 0; }
4.后缀数组
//Achen #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<queue> #include<cmath> const int N=2e6+7; typedef long long LL; using namespace std; int n,sa[N],h[N],rak[N]; char s[N]; template<typename T>void read(T &x) { char ch=getchar(); x=0; T f=1; while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); if(ch=='-') f=-1,ch=getchar(); for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; } void make_hight() { for(int i=0;i<n;i++) rak[sa[i]]=i; for(int i=0,k=0;i<n;i++) { if(!rak[i]) continue; int j=sa[rak[i]-1]; if(k) k--; while(s[i+k]==s[j+k]) k++; h[rak[i]]=k; } } int cmp(int a,int b,int *y,int k) { int o1=a+k>=n?-1:y[a+k]; int o2=b+k>=n?-1:y[b+k]; return o1==o2&&y[a]==y[b]; } void make_sa() { static int t1[N],t2[N],c[N]; int *x=t1,*y=t2,i,k,m='z'+1; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[i]=s[i]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(k=1;k<=n;k<<=1) { int p=0; for(i=n-k;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(i=0;i<m;i++) c[i]=0; for(i=0;i<n;i++) c[x[y[i]]]++; for(i=1;i<m;i++) c[i]+=c[i-1]; for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; p=1; swap(x,y); x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(sa[i],sa[i-1],y,k)?p-1:p++; if(p>=n) break; m=p; } } int main() { scanf("%s",s); n=strlen(s); make_sa(); for(int i=0;i<n;i++) printf("%d ",sa[i]+1); return 0; }
5.后缀自动机
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=2000005; using namespace std; typedef long long LL; int p,np,last=1,cnt=1,l[maxn<<1],fa[maxn<<1],ch[maxn<<1][26],sz[maxn<<1]; LL ans; char s[maxn]; void ins(int c){ p=last; np=++cnt; last=np; l[np]=l[p]+1; for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np; if(!p) fa[np]=1; else{ int q=ch[p][c]; if(l[p]+1==l[q]) fa[np]=q; else{ int nq=++cnt; l[nq]=l[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq; } } sz[np]=1; } void cul(){ static int c[maxn],sa[maxn]; int n=strlen(s); for(int i=1;i<=cnt;i++) c[l[i]]++; for(int i=1;i<=cnt;i++) c[i]+=c[i-1]; for(int i=1;i<=cnt;i++) sa[c[l[i]]--]=i; for(int i=cnt;i>=1;i--){ sz[fa[sa[i]]]+=sz[sa[i]]; if(sz[sa[i]]>=2) ans=max(ans,(LL)sz[sa[i]]*l[sa[i]]); } } int main() { scanf("%s",s); for(int i=0;s[i]!='\0';i++) ins(s[i]-'a'); cul(); printf("%lld\n",ans); return 0; }
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 const int N=4000007; 11 typedef long long LL; 12 using namespace std; 13 int n,c,col[N]; 14 15 template<typename T>void read(T &x) { 16 char ch=getchar(); x=0; T f=1; 17 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 18 if(ch=='-') f=-1,ch=getchar(); 19 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 20 } 21 22 int ecnt,fir[N],nxt[N],to[N],in[N]; 23 void add(int u,int v) { 24 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; in[v]++; 25 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; in[u]++; 26 } 27 28 int tot,rt,p,np,ch[N][11],fa[N],sz[N],l[N]; 29 int insert(int c,int last) { 30 p=last; np=++tot; 31 l[np]=l[p]+1; 32 for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np; 33 if(!p) fa[np]=rt; 34 else { 35 int q=ch[p][c]; 36 if(l[p]+1==l[q]) fa[np]=q; 37 else { 38 int nq=++tot; l[nq]=l[p]+1; 39 memcpy(ch[nq],ch[q],sizeof(ch[q])); 40 fa[nq]=fa[q]; fa[q]=fa[np]=nq; 41 for(;p&&ch[p][c]==q;p=fa[p]) ch[p][c]=nq; 42 } 43 } 44 sz[np]++; return np; 45 } 46 47 void dfs(int x,int fa,int pa) { 48 int last=insert(col[x],pa); 49 for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) { 50 dfs(to[i],x,last); 51 } 52 } 53 54 int main() { 55 read(n); read(c); rt=++tot; 56 for(int i=1;i<=n;i++) read(col[i]); 57 for(int i=1;i<n;i++) { 58 int u,v; 59 read(u); read(v); 60 add(u,v); 61 } 62 for(int i=1;i<=n;i++) if(in[i]==1) 63 dfs(i,0,rt); 64 LL ans=0; 65 for(int i=2;i<=tot;i++) ans+=(LL)l[i]-l[fa[i]]; 66 printf("%lld\n",ans); 67 return 0; 68 }
6.回文自动机
//Twenty #include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> const int maxn=300000+29; using namespace std; typedef long long LL; char s[maxn]; namespace pam{ struct Node{ int len,sz; Node *par,*to[26]; Node(){} Node(int len,Node *par=NULL):len(len),par(par){} }pool[maxn],*pis,*last,*rt[2]; void init(){ pis=pool; rt[1]=new(pis++) Node(-1); rt[0]=new(pis++) Node(0,rt[1]); last=rt[1]->par=rt[1]; } void extend(char *s,int n){ Node* p=last; int c=s[n]-'a'; while(s[n-p->len-1]!=s[n]) p=p->par; if(!p->to[c]){ Node *q=p->par; while(s[n-q->len-1]!=s[n]) q=q->par; p->to[c]=new(pis++) Node(p->len+2,q->to[c]?q->to[c]:rt[0]); } (last=p->to[c])->sz++; } LL query(){ LL ans=0; for(Node *p=pis-1; p!=pool; --p){ p->par->sz+=p->sz; ans=max(ans,(LL)p->sz*p->len); } return ans; } } int main() { scanf("%s",s+1); pam::init(); for(int i=1;s[i];i++){ pam::extend(s,i); } cout<<pam::query()<<endl; return 0; }