zoukankan      html  css  js  c++  java
  • 【POJ1226】Substrings(后缀数组,二分)

    题意:

    n<=10,len<=100

    思路:

    只有一个字符串的时候特判一下

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<map>
    #include<set>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    #define fi first
    #define se second 
    #define MP make_pair
    #define N   210000
    #define MOD 1000000007
    #define eps 1e-8 
    #define pi acos(-1)
    #define oo  1000000000
    
    char ch[N];
    
    int n,i,s[N],sa[N],wa[N],wb[N],wc[N],wd[N],height[N],rank[N],
        a[N],b[N],num[N],M;
    
    int read()
    { 
       int v=0,f=1;
       char c=getchar();
       while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
       while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
       return v*f;
    }
    
    bool cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    
    void getsa(int *r,int *sa,int n,int m)
    {
        int *x=wa,*y=wb,j,p;
        for(i=0;i<n;i++) wc[x[i]=r[i]]++;
        for(i=1;i<m;i++) wc[i]+=wc[i-1];
        for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p)
        {
            p=0;
            for(i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++)
             if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<n;i++) wd[i]=x[y[i]];
            for(i=0;i<m;i++) wc[i]=0;
            for(i=0;i<n;i++) wc[wd[i]]++;
            for(i=1;i<m;i++) wc[i]+=wc[i-1];
            for(i=n-1;i>=0;i--) sa[--wc[wd[i]]]=y[i];
            swap(x,y);
            p=1; x[sa[0]]=0;
            for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
    }
    
    void getheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) rank[sa[i]]=i;
        for(i=0;i<n;height[rank[i++]]=k)
        {
            if(k) k--;
            j=sa[rank[i]-1];
            while(r[i+k]==r[j+k]) k++;
        }
    }
    
    void init()
    {    
            memset(s,0,sizeof(s));
            memset(sa,0,sizeof(sa));
            memset(wa,0,sizeof(wa));
            memset(wb,0,sizeof(wb));
            memset(wc,0,sizeof(wc));
            memset(wd,0,sizeof(wd));
            memset(height,0,sizeof(height));
            memset(rank,0,sizeof(rank));
    }
        
    bool isok(int K)
    {
        int i=1;
        while(i<n)
        {
            i++;
            if(height[i]>=K)
            {
                int st=i;
                while(i<=n&&height[i]>=K) i++;
                for(int j=1;j<=M;j++) b[j]=0; 
                for(int j=max(1,st-1);j<=i-1;j++)
                {
                    int t=sa[j];
                    b[num[t]]++;
                }
                int flag=1;
                for(int j=1;j<=M;j++) 
                 if(!b[j]){flag=0; break;}
                if(flag) return 1;
            }
        }
        return 0;
    }
    
    int main()
    {
        //freopen("poj1226.in","r",stdin);
        //freopen("poj1226.out","w",stdout); 
        int cas;
        scanf("%d",&cas); 
        while(cas--)
        {
            init();
            scanf("%d",&M);
            n=-1;
            int p=0;
            for(int i=1;i<=M;i++) 
            {
                scanf("%s",ch);
                int t=strlen(ch);
                if(M==1) printf("%d
    ",t);
                for(int j=0;j<t;j++) 
                {
                    s[++n]=ch[j]+100;
                    num[n]=i;
                }
                s[++n]=p++;
                num[n]=0;
                for(int j=t-1;j>=0;j--) 
                {
                    s[++n]=ch[j]+100;
                    num[n]=i;
                }    
                s[++n]=p++;
                num[n]=0;
            }
            if(M==1) continue;
            //printf("1
    "); 
            getsa(s,sa,n+1,300);
            getheight(s,sa,n);
            //for(int i=2;i<=n;i++) printf("%d
    ",height[i]);
            int L=1;
            int R=100;
            int last=0;
            while(L<=R)
            {
                int mid=(L+R)>>1;
                if(isok(mid)){last=mid; L=mid+1;}
                 else R=mid-1;
            }
            printf("%d
    ",last);
            memset(num,0,sizeof(num));
        }
        return 0;
    }
         
  • 相关阅读:
    cocos2dx A* + tiledMap
    cocos2dx A*算法
    A*算法
    在VS2012中使用GitHub
    史上最全设计模式导学目录(完整版)
    IT之家
    各种与视频编解码以及视频图像处理的应用相关的新技术,新方法,各种软件开发相关的算法,思想。
    linux下vim命令详解
    两篇很牛的vim使用技巧
    (转)linux下导入、导出mysql数据库命令
  • 原文地址:https://www.cnblogs.com/myx12345/p/9649353.html
Copyright © 2011-2022 走看看