zoukankan      html  css  js  c++  java
  • 回文自动机(BZOJ2565)

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
      int p,next[100001][27],cnt[100001],len[100001],fail[100001],last,a[100001],maxl[100001],maxr[100001];
      char st[100001];
    
      int newnode(int l){
        p++;
        for (int i=1;i<=26;i++) next[p][i]=0;
        cnt[p]=0;
        len[p]=l;
        return(p);
      }
    
      void init(){
        p=-1;
        newnode(0);
        newnode(-1);
        last=1;
        st[0]=-1;
        fail[0]=1;
      }
    
      int get_fail(int po,int x,int num){
        while (a[po-len[x]-1]!=num) x=fail[x];
        return(x);
      }
    
      void add(int po,int c){
        int cur=get_fail(po,last,c);
        if (!next[cur][c]){
          int now=newnode(len[cur]+2);
          fail[now]=next[get_fail(po,fail[cur],c)][c];
          next[cur][c]=now;
        }
        last=next[cur][c];
        cnt[last]++;
      }
    
      void count(){
        for (int i=p;i>=0;i--) cnt[fail[i]]+=cnt[i];
      }
        
      int main(){      
          scanf("%s",&st);
          int n=strlen(st);
          for (int i=1;i<=n;i++) a[i]=st[i-1]-'a'+1;
          
          init();
          for (int i=1;i<=n;i++) 
          add(i,a[i]),maxl[i]=len[last];
          count();
          
          for (int i=1;i<=n/2;i++){
            int t=a[i];a[i]=a[n-i+1];a[n-i+1]=t;    
        }
          init();
          for (int i=1;i<=n;i++) 
          add(i,a[i]),maxr[n-i+1]=len[last];
          count();
      
        int ans=0;    
          for (int i=1;i<n;i++) ans=max(ans,maxl[i]+maxr[i+1]);
          printf("%d
    ",ans);
      }

    每个节点表示一个本质不同的回文串(最多n个)。

    进行count()后,cnt中存每个本质不同的回文串的出现次数。

    ------------------------------------------------------------------------

    CODECHEF APRIL LUNCHTIME 2015 PALPROB

    在fail树上转移palindromness

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #define LL long long
    using namespace std;
    
      map <int,int> mp,mpb;
      int p,tr[110001][27],cnt[110001],len[110001],fail[110001],last,a[110001],maxl[110001],maxr[110001];
      int ans[110001],nd[110001],nxt[110001],des[110001],T,scnt;
      char st[110001];
    
      void addedge(int x,int y){
          nxt[++scnt]=nd[x];des[scnt]=y;nd[x]=scnt;
      }
    
      int newnode(int l){
        p++;
        for (int i=1;i<=26;i++) tr[p][i]=0;
        cnt[p]=0;ans[p]=0;
        len[p]=l;
        return(p);
      }
    
      void init(){
        p=-1;
        newnode(0);newnode(-1);
        last=1;
        st[0]=-1;
        fail[0]=1;
      }
    
      int get_fail(int po,int x,int num){
        while (a[po-len[x]-1]!=num) x=fail[x];
        return(x);
      }
    
      void add(int po,int c){
        int cur=get_fail(po,last,c);
        if (tr[cur][c]==0){
          int now=newnode(len[cur]+2);
          fail[now]=tr[get_fail(po,fail[cur],c)][c];
          tr[cur][c]=now;
        }
        last=tr[cur][c];
        cnt[last]++;
      }
    
      void count(){
        for (int i=p;i>=0;i--) cnt[fail[i]]+=cnt[i];
      }
        
      void dfs(int po){
          if (len[po]>=0){
            int t;
          if (len[po]<=1) t=-1;else t=len[po]/2;
          int p=mp[t];
          if (mpb[t])
            ans[po]=ans[p]+1;else
            ans[po]=1;
        }
        
        mpb[len[po]]=1;mp[len[po]]=po;
        for (int p=nd[po];p!=-1;p=nxt[p])
           dfs(des[p]);
         mpb[len[po]]=0;
      } 
        
      int main(){ 
        freopen("a.in","r",stdin);
      
        scanf("%d",&T);
        while (T--){
          scanf("%s",&st);
          int n=strlen(st);
          for (int i=1;i<=n;i++) a[i]=st[i-1]-'a'+1;
          
          init();
          for (int i=1;i<=n;i++) 
            add(i,a[i]);
          count();    
          
          for (int i=0;i<=p;i++) nd[i]=-1;scnt=0;
          for (int i=0;i<=p;i++) if (i!=1) addedge(fail[i],i);
          
          mp.clear();mpb.clear();
          dfs(1);
          
          LL ret=0;
          for (int i=2;i<=p;i++) ret+=(LL)ans[i]*cnt[i];
          printf("%lld
    ",ret);
        }    
      }
  • 相关阅读:
    【BZOJ 3282】Tree Link Cut Tree模板题
    【BZOJ 2002】【Hnoi 2010】弹飞绵羊 分块||Link Cut Tree 两种方法
    【BZOJ 1507】【NOI 2003】&【Tyvj P2388】Editor 块状链表模板题
    小结-Splay
    【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树
    【BZOJ 3732】 Network Kruskal重构树+倍增LCA
    【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之
    【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
    1020: [SHOI2008]安全的航线flight
    POJ
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/6032530.html
Copyright © 2011-2022 走看看