zoukankan      html  css  js  c++  java
  • bzoj 3172 后缀数组|AC自动机

      后缀数组或者AC自动机都可以,模板题。

    /**************************************************************
        Problem: 3172
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:424 ms
        Memory:34260 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #define maxn 2000010
    #define maxm 300
     
    using namespace std;
     
    struct node{
        int cnt;
        node *fail,*child[30];
        node(){
            cnt=0; fail=NULL;
            memset(child,0,sizeof child);
        }
    } *que[maxn],*root=new(node),*w[maxm];
     
    int n;
     
    int main(){
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            char c[maxn];
            scanf("%s",&c);
            int len=strlen(c);
            node *t=root;
            for (int j=0;j<len;j++){
                if (!t->child[c[j]-'a']) t->child[c[j]-'a']=new(node);
                t=t->child[c[j]-'a']; t->cnt++;
            }
            w[i]=t;
        }
        int h=0,t=1;
        root->fail=root; que[1]=root;
        while (h<t){
            node *u=que[++h];
            for (int i=0;i<26;i++) if (u->child[i]){
                que[++t]=u->child[i];
                node *v=u->fail;
                que[t]->fail=v->child[i]&&v->child[i]!=que[t]?v->child[i]:root;
            } else u->child[i]=u->fail->child[i];
        }
        for (int i=t;i;i--) que[i]->fail->cnt+=que[i]->cnt;
        for (int i=1;i<=n;i++) printf("%d
    ",w[i]->cnt);
        return 0;
    }
    /**************************************************************
        Problem: 3172
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:6660 ms
        Memory:107360 kb
    ****************************************************************/
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 1001000
    #define maxm 300
      
    using namespace std;
      
    int n,len;
    char s[maxn];
    int sa[maxn],tsa[maxn],rk[maxn],trk[maxn],sum[maxn],h[maxn];
    int w[maxn][21];
    int adr[maxm],len_s[maxm];
      
    inline void getsa(int j) {
        for (int i=1;i<=len;i++) sum[i]=0;
        for (int i=1;i<=len;i++) sum[rk[i+j]]++;
        for (int i=1;i<=len;i++) sum[i]+=sum[i-1];
        for (int i=len;i;i--) tsa[sum[rk[i+j]]--]=i;
          
        for (int i=1;i<=len;i++) sum[i]=0;
        for (int i=1;i<=len;i++) sum[rk[i]]++;
        for (int i=1;i<=len;i++) sum[i]+=sum[i-1];
        for (int i=len;i;i--) sa[sum[rk[tsa[i]]]--]=tsa[i];
    }
      
    inline int query(int l,int r) {
        int i,j;
        for (i=0,j=1;(j<<1)<=r-l+1;j<<=1,i++) ;
        return min(w[l][i],w[r-j+1][i]);
    }
      
    int main() {
        scanf("%d",&n); len=0;
        for (int i=1;i<=n;i++) {
            scanf("%s",s+len+1); 
            adr[i]=len+1;
            len=strlen(s+1);
            s[++len]='^';
            len_s[i]=len-adr[i];
        }
        //for (int i=1;i<=len;i++) printf("%c",s[i]); printf("
    ");
        for (int i=1;i<=len;i++) sum[s[i]]++;
        for (int i=1;i<=255;i++) sum[i]+=sum[i-1];
        for (int i=len;i;i--) sa[sum[s[i]]--]=i;
        rk[sa[1]]=1;
        for (int i=2,p=1;i<=len;i++) {
            if (s[sa[i]]!=s[sa[i-1]]) p++;
            rk[sa[i]]=p;
        }
        for (int j=1;j<=len;j<<=1) {
            getsa(j);
            trk[sa[1]]=1;
            for (int i=2,p=1;i<=len;i++) {
                if (rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i]+j]!=rk[sa[i-1]+j]) p++;
                trk[sa[i]]=p;
            }
            for (int i=1;i<=len;i++) rk[i]=trk[i];
        }
        for (int i=1,j=0;i<=len;i++) {
            if (rk[i]==1) continue;
            while (i+j<=len&&sa[rk[i]-1]+j<=len&&s[i+j]==s[sa[rk[i]-1]+j]) j++;
            h[rk[i]]=j;
            if (j) j--;
        }
        //for (int i=1;i<=len;i++) printf("%d ",sa[i]); printf("
    ");
        //for (int i=1;i<=len;i++) printf("%d ",h[i]); printf("
    ");
        memset(w,127,sizeof w);
        for (int i=1;i<=len;i++) w[i][0]=h[i];
        for (int j=1,k=1;j<21;j++,k<<=1)
            for (int i=1;i<=len;i++)
                if (i+k<=len) w[i][j]=min(w[i][j-1],w[i+k][j-1]);
        //for (int i=1;i<=len;i++) printf("%d ",w[i][2]); printf("
    ");
        //printf("%d
    ",query(5,8));
        //printf("%d
    ",rk[6]);
        for (int i=1;i<=n;i++) {
            int l=1,r=rk[adr[i]],mid,left=rk[adr[i]],right=rk[adr[i]];
            while (l<=r) {
                mid=l+r>>1;
                if (query(mid+1,rk[adr[i]])>=len_s[i]) 
                    left=mid,r=mid-1; else l=mid+1;
            }
            l=rk[adr[i]],r=len;
            while (l<=r) {
                mid=l+r>>1;
                if (query(rk[adr[i]]+1,mid)>=len_s[i])
                    right=mid,l=mid+1; else r=mid-1;
            }
            printf("%d
    ",right-left+1);
        }
        return 0;
    }
  • 相关阅读:
    2804 最大最小数质因数
    5429 多重背包
    1851 越狱
    Gvim使用
    3622 假期
    4906 删数问题
    2845 排序的代价
    poj 3352
    常用正则表达式汇总
    功能简单例子
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3724075.html
Copyright © 2011-2022 走看看