bzoj2946: [Poi2000]公共串

来源:互联网 发布:矩阵探索 生命补给改 编辑:程序博客网 时间:2024/05/22 16:45

将所有串连起来,中间加一个分隔符,二分答案,有连续ht>=mid且每个串中都出现一次就合法,否则不合法,一定要将分隔符特判掉,否则=0会输出1。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int read(){    char ch=getchar();int f=0;    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9') {f=f*10+(ch^48);ch=getchar();}    return f;}char s[10100],temp[2005];int tar[8],now,v[15005],ans,n,T,tot;int sa1[15005],sa2[15005],rk1[15005],rk2[15005];int *sa,*SA,*rk,*RK,ht[15005];bool vis[8];bool check(int x){    memset(vis,0,sizeof(vis));    tot=1;    for(int i=T;i;i--)    {        if(sa[1]>tar[i])        {            vis[i]=1;            break;        }    }    for(int i=2;i<=n;i++)    {        if(s[sa[i]]=='~')        break;        if(ht[i]>=x)        {            for(int j=T;j;j--)            {                if(sa[i]>tar[j])                {                    if(!vis[j])                    {                        vis[j]=1;                        tot++;                        if(tot==T)                        return 1;                    }                    break;                }            }        }        else        {            memset(vis,0,sizeof(vis));            for(int j=T;j;j--)            {                if(sa[i]>tar[j])                {                    vis[j]=1;                    break;                }            }            tot=1;        }    }    return 0;}int main(){    T=read();int l=0,r=20000;    for(int i=1;i<=T;i++)    {        tar[i]=++now;        s[now]='~';        scanf("%s",temp+1);        n=strlen(temp+1);        r=min(r,n);        for(int j=1;j<=n;j++)        {            s[++now]=temp[j];        }    }    n=now;    sa=sa1,SA=sa2;rk=rk1;RK=rk2;    for(int i=1;i<=n;i++) v[s[i]]++;    for(int i=1;i<=200;i++) v[i]+=v[i-1];    for(int i=n;i;i--) sa[v[s[i]]--]=i;    for(int i=1;i<=n;i++) rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);    for(int k=1;k<=n;k<<=1)    {        for(int i=1;i<=n;i++) v[rk[sa[i]]]=i;        for(int i=n;i;i--) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;        for(int i=n-k+1;i<=n;i++) SA[v[rk[i]]--]=i;        for(int i=1;i<=n;i++) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]);        swap(rk,RK);swap(sa,SA);        if(rk[sa[n]]==n)        break;    }    int k=0;    for(int i=1;i<n;i++)    {        while(s[sa[rk[i]]+k]==s[sa[rk[i]-1]+k]) k++;        ht[rk[i]]=k;        if(k) k--;    }    while(l<=r)    {        int mid=l+r>>1;        if(check(mid))        {            ans=mid;            l=mid+1;        }        else r=mid-1;    }    cout<<ans;}
原创粉丝点击