spoj220

题解:

后缀数组

把所有串连接起来

二分答案

代码:

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<cmath>  
const int N=200005;
typedef long long ll;
using namespace std;
char ch[N];  
int str[N],l[N],mx[N],mn[N],in[N],k,wa[N],wb[N],wv[N],Ws[N],sa[N],Rank[N],height[N];
int cmp(int *r,int a,int b,int l)    
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}    
void da(const int *r,int *sa,int n,int m)
{    
    int *x=wa,*y=wb;     
    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];
        swap(x,y);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++;     
    }     
}    
void calheight(const int *r,int *sa,int n)
{    
    int j,k=0;    
    for (int i=1;i<=n;i++) Rank[sa[i]]=i;    
    for (int i=0;i<n;height[Rank[i++]]=k)    
     for (k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);      
}  
int pd(int mid,int n)
{  
    for (int i=0;i<k;i++){mx[i]=0;mn[i]=1e9;}   
    for (int i=1;i<=n;i++)
     {  
        if (height[i]<mid)
         {  
            for (int j=0;j<k;j++)
             {  
                mx[j]=0;  
                mn[j]=1e9;  
             }  
            mx[in[sa[i]]]=sa[i];  
            mn[in[sa[i]]]=sa[i];  
         }  
        else
         {  
            mx[in[sa[i]]]=max(mx[in[sa[i]]],sa[i]);  
            mn[in[sa[i]]]=min(mn[in[sa[i]]],sa[i]);  
            mx[in[sa[i-1]]]=max(mx[in[sa[i-1]]],sa[i-1]);  
            mn[in[sa[i-1]]]=min(mn[in[sa[i-1]]],sa[i-1]); 
            int j; 
            for (j=0;j<k;j++)
             if (mx[j]-mn[j]<mid)break;
            if (j==k) return 1;  
         }  
     }  
    return 0;  
}  
int main()
{  
    int cnt=0,t;  
    scanf("%d",&t);  
    while (t--)
     {  
        scanf("%d",&k);  
        int n=0;  
        for (int i=0;i<k;i++)
         {  
            scanf("%s",ch);  
            l[i]=strlen(ch);  
            for (int j=n;j<n+l[i];j++)
             {  
                str[j]=ch[j-n]-'a'+1;  
                in[j]=i;  
             }  
            n+=l[i]+1;  
            str[n-1]=27+i;  
         }  
        n--;  
        str[n]=0;  
        da(str,sa,n+1,27+k+5);  
        calheight(str,sa,n);  
        int l=0,r=10000;  
        while (l<r)
         {  
            int mid=(l+r+1)/2;  
            if (pd(mid,n))l=mid; 
            else r=mid-1;  
         }  
        printf("%d
",l);  
     }  
    return 0;  
}  
原文地址:https://www.cnblogs.com/xuanyiming/p/8535184.html