zoukankan      html  css  js  c++  java
  • poj1226

    题解:

    后缀数组

    把所有串先翻转,用一个没有出现过的字符连接

    然后再把所有串接起来

    然后用一个没有出现过的字符连接

    然后二分

    在后缀数组上判断lcp

    代码:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long LL;
    const int N=100*100*5;
    char str[105];
    int r[N],len,n,t,Index[N],Rank[N],height[N],sa[N],wa[N],wb[N],wv[N],WS[N];
    int cmp(int *r,int a,int b,int l)
    {
        return r[a]==r[b]&&r[a+l]==r[b+l];
    }
    void da(int *r,int *sa,int n,int m)
    {
        int p,*x=wa,*y=wb,*t;
        for (int i=0;i<m;i++)WS[i]=0;
        for (int i=0;i<n;i++)WS[x[i]=r[i]]++;
        for (int i=1;i<m;i++)WS[i]+=WS[i-1];
        for (int i=n-1;i>=0;i--)sa[--WS[x[i]]]=i;
        for (int j=1,p=1;p<n;j*=2,m=p)
         {
             p=0;
            for (int i=n-j;i<n;i++)y[p++]=i;
            for (int i=0;i<n;i++)
             if (sa[i]>=j)y[p++]=sa[i]-j;
            for (int i=0;i<n;i++)wv[i]=x[y[i]];
            for (int i=0;i<m;i++)WS[i]=0;
            for (int i=0;i<n;i++)WS[wv[i]]++;
            for (int i=1;i<m;i++)WS[i]+=WS[i-1];
            for (int i=n-1;i>=0;i--)sa[--WS[wv[i]]]=y[i];
            t=x,x=y,y=t,p=1,x[sa[0]]=0;     
            for (int i=1;i<n;i++)
             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
         } 
        return;
    }
    void calheight(int *r,int *sa,int n)
    {
        int k=0;
        for (int i=1;i<=n;i++)Rank[sa[i]]=i;
        for (int i=0;i<n;height[Rank[i++]]=k)
         {
             k?k--:0;
             for (int j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
         }
        return;
    }
    int check(int x)
    {
        set<int>se;
        for (int i=1;i<len;i++)
         {
            if (height[i]>=x)
             { 
                se.insert(Index[sa[i]]);
                se.insert(Index[sa[i-1]]);
             }
            else
             {
                if (se.size()==n)return 1;
                se.clear();
             }
         }
        if (se.size()==n)return 1;
        return false;
    }
    void solve()
    {
        int L=1,R=100,ans=0;
        while (R>=L)
         {
            int mid=(L+R)/2;
            if (check(mid))
             {
                ans=mid;
                L=mid+1;
             }
            else R=mid-1;
         }
        printf("%d
    ",ans);
    }
    int main()
    {
        scanf("%d", &t);
        while (t--)
         {
            scanf("%d",&n);len=0;
            for (int i=1,val=0;i<=n;i++)
             {
                scanf("%s",&str);
                for (int j=0;j<strlen(str);j++)
                 { 
                    Index[len]=i; 
                    r[len++]=(str[j]-'A'+2*n+1);
                 }
                Index[len]=i; 
                r[len++]=val++; 
                for (int j=strlen(str)-1;j>=0;j--)
                 {
                    Index[len]=i;
                    r[len++]=(str[j]-'A'+2*n+1);
                 }
                Index[len]=i;
                r[len++]=val++; 
             }
            da(r,sa,len,300);
            calheight(r,sa,len-1);
            solve();
         }
        return 0;
    }
  • 相关阅读:
    eval解析的函数传参 object array
    whistle证书过期或不信任
    isa hasa的区别、及理解
    JVM工作原理和特点
    Cookie跨域操作
    关闭当前窗口js
    css遮罩层
    js 获得两个数组的重复元素
    主页变灰
    js 格式化日期
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8490228.html
Copyright © 2011-2022 走看看