[NOIP模拟题]FGD的密码

来源:互联网 发布:淘宝订单在线生成器 编辑:程序博客网 时间:2024/05/17 08:26

Description
FGD的眼睛瞪得像苹果,他还计划中午回到母舰去他家旁边的咖啡厅去喝一杯呢。看来咖啡是暂时泡汤了。
“据说,为了预防日益增加的逃兵问题,这战机的引擎没有舰长的命令,是无法关闭,只能向前的。”
“好!现在我下令让他关闭!”
“可是,我们都不知道该怎么关掉他。”
……
FGD走到动力舱,一脚踢开在控制台上焦头烂额的工程师,自己坐了上去。
一小时后……
FGD发现每当他想关闭引擎的时候,就会有一大堆乱码跳出来,他便会不由自主地去阅读那一大段无规律的文字,阻止他的正常思维,使得他没有空闲时间去按下对话框的确定。
一天后……
FGD终于有点头绪了,他发现这段文字并不是完全漫无规律的,这段仅仅由小写字母组成的文字可以被分为长度相同的若干行,每行都有一串相同的连续的文字,隐藏在其他乱码中间。FGD以他敏锐的大脑相信,那段最长的被重复的文字一定包含有惊天的大秘密。现在你帮忙告诉他那段文字的长度吧。

Input
输入文件第一行为两个整数nl,表示这段文字共可以分为n行,每行的长度均为l。(1<=n<=10,1<=l<=10000
接下来n行为那n行仅有小写字母组成的文字。

Output
要求输出文件仅包含一行,一个整数,为这n行文字都包含的最长的一段连续的文字的长度。

Sample Input
2 5
ababc
cabac

Sample Output
3

HINT

思路
首先将几个串连在一起,然后把最长不重叠子串改一改就好了。

代码

#include <cstdio>#include <algorithm>const int maxn=300000;char s[maxn+10],t[maxn+10];int m,len,pos[maxn+10];struct suffix_array{  int rank[maxn+10],sa[maxn+10],sum[maxn+10],tmp[maxn+10],h[maxn+10];  inline int suffix_sort(int n)  {    int m=127,p=1,len=1;    int* x=rank;    int* y=tmp;    for(register int i=1; i<=n; ++i)      {    x[i]=s[i];    y[i]=i;    ++sum[x[i]];      }    for(register int i=1; i<=m; ++i)      {    sum[i]+=sum[i-1];      }    for(register int i=n; i; --i)      {    sa[sum[x[i]]]=i;    --sum[x[i]];      }    while(p<n)      {    m=p;    p=0;    for(register int i=0; i<=m; ++i)      {        sum[i]=0;      }    for(register int i=n-len+1; i<=n; ++i)      {        ++p;        y[p]=i;      }    for(register int i=1; i<=n; ++i)      {        if(sa[i]-len>0)          {        ++p;        y[p]=sa[i]-len;          }      }    for(register int i=1; i<=n; ++i)      {        ++sum[x[y[i]]];      }    for(register int i=1; i<=m; ++i)      {        sum[i]+=sum[i-1];      }    for(register int i=n; i; --i)      {        sa[sum[x[y[i]]]]=y[i];        --sum[x[y[i]]];      }    std::swap(x,y);    p=1;    x[sa[1]]=1;    for(register int i=2; i<=n; ++i)      {        if(!((y[sa[i]]==y[sa[i-1]])&&(y[sa[i]+len]==y[sa[i-1]+len])))          {        ++p;          }        x[sa[i]]=p;      }    len<<=1;      }    p=0;    for(register int i=1; i<=n; ++i)      {    ++p;    rank[sa[i]]=p;      }    return 0;  }  inline int get_height(int n)  {    int k=0;    for(register int i=1; i<=n; ++i)      {    if(k)      {        --k;      }    int j=sa[rank[i]-1];    while(s[i+k]==s[j+k])      {        ++k;      }    h[rank[i]]=k;      }    return 0;  }  inline int judge(int x,int n)  {    int b[11],cnt=1;    for(register int i=1; i<=m; ++i)      {    b[i]=0;      }    b[pos[sa[1]]]=1;    for(int i=2; i<=n; ++i)      {    if(h[rank[sa[i]]]<x)      {        for(register int j=1; j<=m; ++j)          {        b[j]=0;          }        cnt=1;        b[pos[sa[i]]]=1;      }    else if(!b[pos[sa[i]]])      {        b[pos[sa[i]]]=1;        ++cnt;      }    if(cnt>=m)      {        return 1;      }      }    return 0;  }  inline int work(int n)  {    suffix_sort(n);    get_height(n);    int left=0,right=len;    while(left<=right)      {    int mid=(left+right)>>1;    if(judge(mid,n))      {        left=mid+1;      }    else      {        right=mid-1;      }      }    return left-1;  }};suffix_array sa;int main(){  scanf("%d%d",&m,&len);  int x=0;  for(register int i=1; i<m; ++i)    {      scanf("%s",t+1);      for(register int j=1; j<=len; ++j)    {      s[x+j]=t[j];      pos[x+j]=i;    }      x+=len+1;      s[x]='~';    }  scanf("%s",t+1);  for(register int i=1; i<=len; ++i)    {      s[x+i]=t[i];      pos[x+i]=m;    }  x+=len;  printf("%d\n",sa.work(x));  return 0;}
原创粉丝点击