码迷,mamicode.com
首页 > 编程语言 > 详细

hdu 2459 Maximum repetition substring(后缀数组)

时间:2017-02-05 13:57:16      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:href   ++   ima   bsp   div   csdn   min   return   c++   

题目链接:hdu 2459 Maximum repetition substring

题意:

让你找一个重复最多的子串,并且输出。

题解:

这个是论文题,看的cxlove的题解,不是很理解为什么这样就能完全找完,当作结论使吧。

技术分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4 namespace suffixarray{    
 5     #define FN(n) for(int i=0;i<n;i++)
 6     const int N =1E5+7;//字符串长度
 7     int rnk[N],sa[N],height[N],c[N];char s[N];
 8     void getsa(int n,int m,int *x=rnk,int *y=height){
 9         FN(m)c[i]=0;FN(n)c[x[i]=s[i]]++;FN(m)c[i+1]+=c[i];
10         for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
11         for(int k=1,p;p=0,k<=n;k=p>=n?N:k<<1,m=p){
12             for(int i=n-k;i<n;i++)y[p++]=i;
13             FN(n)if(sa[i]>=k)y[p++]=sa[i]-k;
14             FN(m)c[i]=0;FN(n)c[x[y[i]]]++;FN(m)c[i+1]+=c[i];
15             for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
16             swap(x,y),p=1,x[sa[0]]=0;
17             for(int i=1;i<n;i++)
18             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
19         }
20         FN(n)rnk[sa[i]]=i;
21         for(int i=0,j,k=0;i<n-1;height[rnk[i++]]=k)
22         for(k=k?k-1:k,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++);
23     }
24 }
25 using namespace suffixarray;
26 
27 int f[N][20],ans[N],cas;
28 void rmq(int *a,int n)
29 {
30     for(int i=1;i<=n;i++)f[i][0]=a[i];
31     for(int j=1;1<<j<n;j++)for(int i=1;i<=n;i++)
32     if(i+(1<<j)-1<=n)f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
33     else break;
34 }
35 inline int find(int l,int r)
36 {
37     l=rnk[l],r=rnk[r];
38     if(l>r)swap(l,r);
39     l++;
40     int k=31-__builtin_clz(r-l+1);
41     return min(f[l][k],f[r-(1<<k)+1][k]);
42 }
43 
44 int main()
45 {
46     while(scanf("%s",s),s[0]!=#)
47     {
48         int len=strlen(s);
49         getsa(len+1,130);
50         rmq(height,len);
51         int cnt=0,mx=0;
52         F(l,1,len-1)for(int i=0;i+l<len;i+=l)
53         {
54             int r=find(i,i+l);
55             int step=r/l+1,k=i-(l-r%l);
56             if(k>=0&&r%l)step+=(find(k,k+l)>=r);
57             if(step>mx)
58             {
59                 mx=step,cnt=0;
60                 ans[cnt++]=l;
61             }else if(step==mx)ans[cnt++]=l;
62         }
63         int tmp=-1,st;
64         for(int i=1;i<=len&&tmp==-1;i++)F(j,0,cnt-1)
65         {
66             int l=ans[j];
67             if(find(sa[i],sa[i]+l)>=(mx-1)*l)
68             {
69                 tmp=l,st=sa[i];
70                 break;
71             }
72         }
73         printf("Case %d: ",++cas);  
74         for(int i=st,j=0;j<tmp*mx;j++,i++) printf("%c",s[i]);  
75         printf("\n");
76     }
77     return 0;
78 }
View Code

 

hdu 2459 Maximum repetition substring(后缀数组)

标签:href   ++   ima   bsp   div   csdn   min   return   c++   

原文地址:http://www.cnblogs.com/bin-gege/p/6367338.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!