POJ 2774 Long Lon…

来源:互联网 发布:淘宝水印logo设计 编辑:程序博客网 时间:2024/06/06 03:58
题目链接:http://poj.org/problem?id=2774

给出两个长度均不大于100000的字符串

求出这两个字符串的最长公共子串。

#include <iostream>
#include <cstdio>
#include <cstring>
const int N=100005*2;
int suff[N],r[N],Height[N],rank[N];
int wa[N],cnt[N],wb[N],wv[N];
int len1,len;
char str[N];
int cmp(int *v,int a,int b,int h)
{
     return v[a]==v[b]&&v[a+h]==v[b+h] ;
     //这里要满足从a和b开始长度为h的前缀相同以及从a+h和b+h开始长度为h的前缀相同,
     //这样才能判定长度为2h的前缀相同
}
void CreatSuff(int n,int m)
{
      int i,h,p;//用计数排序求出长度为1的suff值
      int *x=wa,*t,*y=wb;
      for(i=0;i<m;i++)
          cnt[i]=0;
      for(i=0;i<n;i++)
          cnt[x[i]=r[i]]++;
      for(i=1;i<m;i++)
          cnt[i]+=cnt[i-1];
      for(i=n-1;i>=0;i--)
              suff[--cnt[x[i]]]=i;   //其中x存放rank的值,以上是计数排序模块
      //根据suff求出rank,再利用长度为h的rank为关键字,基数排序,求出长度为2*h的suff.
      for(h=1,p=0;p<n;h<<=1,m=p)
      {
            for(p=0,i=n-h;i<n;i++)
               y[p++]=i;
           //y存放第二关键字排序的结果,这里有点技巧,你用上次的suff对第二关键子排序
            for(i=0;i<n;i++)
               if(suff[i]>=h)
                  y[p++]=suff[i]-h;
            for(i=0;i<n;i++)             //对第一关键字进行计数排序
                 wv[i]=x[y[i]];
            for(i=0;i<m;i++)
                 cnt[i]=0;
            for(i=0;i<n;i++)
                 cnt[wv[i]]++;
            for(i=1;i<m;i++)
                 cnt[i]+=cnt[i-1];
            for(i=n-1;i>=0;i--)
                 suff[--cnt[wv[i]]]=y[i];
            t=x;x=y;y=t;p=1;
            //利用suff求rank,变量p其实是不同字符串的个数,这里让m=p,当p=len时就结束
            for(x[suff[0]]=0,i=1;i<n;i++)
                 x[suff[i]]=cmp(y,suff[i],suff[i-1],h) ? p-1 : p++;
      }
}
void Calheight()
{
    inti,j,k=0;
   for(i=1;i<=len;i++)
       rank[suff[i]]=i;
   for(i=0;i<=len;Height[rank[i++]]=k)
       for(k?k--:0,j=suff[rank[i]-1];str[i+k]==str[j+k];k++);
   return;
}
bool Judge(int c) //判断是否分别属于两个字串
{
     if(suff[c]>=len1&&suff[c-1]>=len1)
         return  false;
     elseif(suff[c]<len1&&suff[c-1]<len1)
         return  false;
     else
         return  true;
}
int main()
{
   scanf("%s",str);
   len1=strlen(str);
   str[len1]=1;      //觉得中间不加字符,也应该是对的,但这样Runtime Error,还没想清楚
   scanf("%s",str+len1+1);
   len=strlen(str);
    for(inti=0;i<len;i++)
       r[i]=str[i];
   CreatSuff(len+1,128);
   Calheight();
    intMax=0;
    intresult=0;
    for(inti=2;i<=len;i++)
    {
       if(result<Height[i]&&Judge(i))
           result=Height[i];
    }
   printf("%d\n",result);
    return0;
}
0 0
原创粉丝点击