POJ 3693 Maximum repetition substring(后缀数组+ST)
来源:互联网 发布:下载ps软件 编辑:程序博客网 时间:2024/04/30 22:28
Description
给出一个字符串,求这个字符串的一个子串,使得其完全由最小循环节组成且循环次数最多,如果有多组解则输出字典序最小的
Input
多组用例,每组用例占一行为一行长度不超过100000的字符串,以#结束输入
Output
对于每组用例,输出满足条件的字典序最小的子串
Sample Input
ccabababc
daabbccaa
#
Sample Output
Case 1: ababab
Case 2: aa
Solution
如果某子串是由几个最小循环节构成,设最小循环节长度为l,那么s[0],s[l],s[2l],…,s[[len/l]*l]中至少由两个出现在这个子串中,那么从1到n枚举l,对于每个i,求出k=lcp(i,i+l)(用ST表预处理height数组可以O(1)查询区间最小值求lcp(a,b)),那么循环次数最少为cnt=k/l+1次,但这样是假设i和i+l是两个循环节的起始,但很多情况下不是,所以还需要往i前面移动一点寻求更长的匹配,移动的长度就是l-k%l,因为剩余的k%l已经有匹配了,如果能把剩下的l-k%l匹配上,那么循环节次数就多了一个,所以下次求kk=lcp(t,t+l),其中t=i-(l-k%l),如果kk>=k则cnt++,之后拿cnt更新最优解即可,注意要将循环节次数相等的l值都记录下来放到ans数组中,因为之后需要从中找字典序最小的,找最小字典序的解就是按sa数组往下寻找,对于每个sa[i],如果lcp(sa[i],sa[i]+ans[j])>=(Max-1)*ans[j],则说明从sa[i]开始,长度为Max*ans[j]的子串就是符合条件的最优解
Code
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;#define maxn 111111int t1[maxn],t2[maxn],c[maxn],sa[maxn],rank[maxn],height[maxn];bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int str[],int n,int m){ n++; int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=str[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1) { p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p>=n)break; m=p; } int k=0; n--; for(i=0;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;i++) { if(k)k--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; }}int RMQ[maxn],mm[maxn],best[22][maxn];void Init_rmq(int n){ for(int i=1;i<=n;i++)RMQ[i]=height[i]; mm[0]=-1; for(int i=1;i<=n;i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(int i=1;i<=n;i++)best[0][i]=i; for(int i=1;i<=mm[n];i++) for(int j=1;j+(1<<i)-1<=n;j++) { int a=best[i-1][j]; int b=best[i-1][j+(1<<(i-1))]; if(RMQ[a]<RMQ[b])best[i][j]=a; else best[i][j]=b; }}int Ask_rmq(int a,int b){ int t; t=mm[b-a+1]; b-=(1<<t)-1; a=best[t][a];b=best[t][b]; return RMQ[a]<RMQ[b]?a:b;}int lcp(int a,int b){ a=rank[a];b=rank[b]; if(a>b)swap(a,b); return height[Ask_rmq(a+1,b)];}int n,a[maxn],ans[maxn],res;char s[maxn];int main(){ int Case=1; while(~scanf("%s",s),s[0]!='#') { n=strlen(s); for(int i=0;i<n;i++)a[i]=s[i]; a[n]=0; da(a,n,333); Init_rmq(n); int Max=-1; for(int l=1;l<n;l++) { for(int i=0;i+l<n;i+=l) { int k=lcp(i,i+l); int cnt=k/l+1,t=l-k%l; t=i-t; if(t>=0&&k%l) if(lcp(t,t+l)>=k)cnt++; if(cnt>Max) { Max=cnt; res=0; ans[res++]=l; } else if(cnt==Max)ans[res++]=l; } } int pos,len,flag=0; for(int i=1;i<=n;i++) { if(flag)break; for(int j=0;j<res;j++) { int temp=ans[j]; if(lcp(sa[i],sa[i]+temp)>=(Max-1)*temp) { pos=sa[i]; len=Max*temp; flag=1; break; } } } printf("Case %d: ",Case++); for(int i=0;i<len;i++)printf("%c",s[i+pos]); printf("\n"); } return 0;}
- POJ 3693 Maximum repetition substring(后缀数组+ST)
- Poj 3693 Maximum repetition substring|后缀数组|st表
- poj 3693 Maximum repetition substring //后缀数组
- poj 3693 Maximum repetition substring (后缀数组)
- poj 3693 Maximum repetition substring(后缀数组)
- poj 3693 Maximum repetition substring(后缀数组)
- 【后缀数组】【poj 3693】Maximum repetition substring
- POJ 3693 Maximum Repetition Substring 后缀数组
- poj 3693 Maximum repetition substring(后缀数组好题)
- POJ 3693 Maximum repetition substring(RMQ+后缀数组)
- POJ 3693 Maximum repetition substring (后缀数组)
- POJ 3693 - Maximum repetition substring (后缀数组)
- POJ 3693 Maximum repetition substring(后缀数组)
- poj 3693 Maximum repetition substring (后缀数组+RMQ)
- [POJ3693]Maximum repetition substring(后缀数组+st)
- 【后缀数组】 HDOJ 2459 && POJ 3693 Maximum repetition substring
- poj 3693 Maximum repetition substring(有点麻烦的后缀数组)
- POJ 3693 Maximum repetition substring(后缀数组神题)
- 完美长方体是不可能存在的 第四章
- APP解构重构.勿忘初心
- Thinkphp S方法的redis配置
- leetcode51/52-N-Queens I/II(n皇后问题)
- eclipse mar整合lombok
- POJ 3693 Maximum repetition substring(后缀数组+ST)
- Python实现欧拉计划20题
- android捕获子进程的异常操作
- 系统自带的截图工具遇到无法保存的问题
- 利用de Casteljau算法绘制Bezier曲面
- linux进程调度,优先级、进程nice值
- nyoj_10 skiing
- StringIO和BytesIO
- 利用FMDB增加表字段