字符串算法模板

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;
}
KMP

 

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;
}
AC自动机 指针版
//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;
}
AC自动机 洛谷加强版
//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;
}
AC自动机 数组版

 

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;
}
Manacher

 

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;
}
回文自动机

 

posted @ 2017-09-04 18:22  啊宸  阅读(189)  评论(0编辑  收藏  举报