• 字符串算法模板


    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]!='';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]!='';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
    ",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]!='';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]!='';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("【
    ");
       printf("%d
    ",tot);
       for(int i=1;i<=cs;i++) {
       for(int j=0;ch[an[i]][j]!='';j++)
       printf("%c",ch[an[i]][j]);
       printf("
    ");
       }//printf("】
    ");
       }
       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]!='';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]!='';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
    ",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
    ",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]!='';i++) ins(s[i]-'a');
        cul();
        printf("%lld
    ",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
    ",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;
    }
    回文自动机
  • 相关阅读:
    网络七层
    微信小程序开发工具 常用快捷键
    BZOJ 1026 windy数 (数位DP)
    BZOJ 1026 windy数 (数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3709 Balanced Number (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7474939.html
Copyright © 2020-2023  润新知