最大连续重复子串

问题描述:寻找一个字符串中的某个子串,它是由某个字符串"连续重复构成",求出“连续重复次数最多”构成的那个sub—字符串。如果存在多个结果,求出字典排序最小的一个。

比如对于字符串abababcc,“ababab”是最大连续重复子串,其中“ab”重复次数是3。

再比如:bbbaaa,问题的答案是“aaa”,”a“重复3次构成。虽然"bbb"也是由"b"连续三次构成,但是字典排序"aaa"<"bbb"。

 

问题求解:

这个问题可以把”连续重复字符串“看作一个子问题(参看之前blog),然后遍历整个字符串的长度L,对每个长度为L的子串都调用”子问题“,分别求出每个子串的next数组,最后取重复次数最多的结果(如果唯一,否则,字典排序子串)。

 

这样的时间复杂度很高,但是实在也想不出什么高效的算法,杯具……

#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; int next[100010]; char s[100010]; char max_s[100010]; int max_times; void get_next(int n,char *s) { int i=0; next[i]=-1; int j=next[0]; while(i<=n) { if(j==-1 || s[i]==s[j]) { i++; j++; next[i]=j; } else j = next[j]; } } void solve(int st,int en) { memset(next,0,sizeof(next)); int len = en-st+1; get_next(len,s+st); int t = len - next[len]; int times = 1; if(len%t==0) { times = len/t; } else times=1; if(max_times == len/t) { char *tmp_s = new char[t+1]; memset(tmp_s,0,sizeof(tmp_s)); strncpy(tmp_s,s+en+1-t,t); if(strcmp(max_s,tmp_s)>0) { memset(max_s,0,sizeof(max_s)); strncpy(max_s,s+en+1-t,t); } delete []tmp_s; } if(max_times<times) { max_times = times; memset(max_s,0,sizeof(max_s)); strncpy(max_s,s+en+1-t,t); } } int main() { scanf("%s",s); int c=1; while(s[0]!='#') { int i,j; int l = strlen(s); for(i=0;i<l;i++) for(j=i;j<l;j++) { if(j-i+1<max_times) continue; solve(i,j); } printf("Case %d:",c); for(i=0;i<max_times;i++) printf("%s",max_s); cout<<endl; memset(s,0,sizeof(s)); memset(next,0,sizeof(next)); memset(max_s,0,sizeof(max_s)); max_times=0; c++; scanf("%s",s); } }

你可能感兴趣的:(最大连续重复子串)