【POJ1743】不可重叠最长重复子串

 

  题意:求一个字符串里两个不重叠的最长重复子串

 

 

 

 

 

 代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 using namespace std;
  6 
  7 int sa[20010],rank[20010],y[20010],Rsort[20010];
  8 int wr[20010],a[20010],height[20010],n;
  9 
 10 bool cmp(int k1,int k2,int ln){return wr[k1]==wr[k2] && wr[k1+ln]==wr[k2+ln];}
 11 
 12 void get_sa(int m) 
 13 {
 14   int i,k,p,ln;
 15 
 16   memcpy(rank,a,sizeof(rank));
 17 
 18   memset(Rsort,0,sizeof(Rsort));
 19   for (i=1;i<=n;i++) Rsort[rank[i]]++;
 20   for (i=1;i<=m;i++) Rsort[i]+=Rsort[i-1];
 21   for (i=n;i>=1;i--) sa[Rsort[rank[i]]--]=i; 
 22   
 23   ln=1; p=0; 
 24   while (p<n)
 25   {
 26       for (k=0,i=n-ln+1;i<=n;i++) y[++k]=i;
 27       for (i=1;i<=n;i++) if (sa[i]>ln) y[++k]=sa[i]-ln;
 28       for (i=1;i<=n;i++) wr[i]=rank[y[i]];
 29       
 30       memset(Rsort,0,sizeof(Rsort));
 31       for (i=1;i<=n;i++) Rsort[wr[i]]++;
 32       for (i=1;i<=m;i++) Rsort[i]+=Rsort[i-1];
 33       for (i=n;i>=1;i--) sa[Rsort[wr[i]]--]=y[i];
 34 
 35       memcpy(wr,rank,sizeof(wr));   
 36       p=1; rank[sa[1]]=1;
 37       for (i=2;i<=n;i++)
 38       {
 39          if (!cmp(sa[i],sa[i-1],ln)) p++;
 40          rank[sa[i]]=p;
 41       }
 42       m=p; ln*=2;
 43   }
 44   a[0]=sa[0]=0;
 45 }
 46 
 47 void get_he()
 48 {
 49   int i,j,k=0;
 50   for (i=1;i<=n;i++)
 51   {
 52      j=sa[rank[i]-1];
 53      if (k) k--;
 54     
 55      while (a[j+k]==a[i+k]) k++;
 56      height[rank[i]]=k;
 57   }
 58 }
 59 
 60 bool check(int k)
 61 {
 62     int i,maxx=0,minn=20010;
 63     for(i=1;i<=n;i++)
 64     {
 65         if(height[i]<k) maxx=minn=sa[i];
 66         else
 67         {
 68             if(sa[i]>maxx) maxx=sa[i];
 69             if(sa[i]<minn) minn=sa[i];
 70             if(maxx-minn>k) return 1;
 71         }
 72     }
 73     return 0;
 74 }
 75 
 76 int hd_work()
 77 {
 78     int l,r,mid,ans=0;
 79     l=1;r=n;
 80     while(l<=r)
 81     {
 82         mid=(l+r)/2;
 83         if(check(mid)) 
 84         {
 85           l=mid+1;
 86           ans=mid;
 87         }
 88         else r=mid-1;
 89     }
 90     if(ans>=4) ans++;
 91     else ans=0;
 92     return ans;
 93 }
 94 
 95 int main()
 96 {
 97     int i,a1,a2;
 98     while(1)
 99     {
100         scanf("%d",&n);
101         if(n==0) break;
102         scanf("%d",&a1);
103         for(i=2;i<=n;i++)
104         {
105             scanf("%d",&a2);
106             a[i-1]=a2-a1+88;
107             a1=a2;
108         } 
109         n--;
110         get_sa(20010);
111         get_he();
112         printf("%d\n",hd_work());
113     }
114 }
poj1743

 

2015-12-15 17:09:09

转载于:https://www.cnblogs.com/Konjakmoyu/p/5048791.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值