题目:求出字符串的不重叠的最长重复子串的长度。
这道题目可以说是后缀数组的简单应用,当然也可以用KMP来解。很容易想到直接求从i=0开始求最大的Height值,满足suff[i-1]+Height[i]=suff[i]或suff[i]+Height[i]=suff[i-1]即可,而且这样提交也AC了,数据实在太弱了,其实这样是错的,在网上找了这组数据“defgdefgzdefge”这样过不了,原因是Height被0分成了不连续的段。应该先对长度k二分再枚举才可以。判定是否存在两个长度为k的字串相同,且正好相连。但这样比较耗时,不知如何优化.
错误的代码:
bool Judge(int c)
{
if(suff[c-1]+H[c]==suff[c]||suff[c]+H[c]==suff[c-1])
return true;
return false;
}
int main()
{
freopen("data.in","r",stdin);
scanf("%d",&test);
while(test--)
{
scanf("%s",str);
len=strlen(str);
for(int i=0;i<len;i++)
r[i]=str[i];
CreatSuff(150);
CalHeight();
int Max=0;
for(int i=1;i<len;i++)
if(Max<H[i]&&Judge(i)) //这儿错了,Height被一些零点隔开了
Max=H[i];
printf("%d/n",Max);
}
return 0;
}
改正后的代码:
bool Check(int k)
{
for(int i=0;i<len;i++)
{
if(H[i]>=k) //枚举Height>=k的区间,若存在两个连续的长度为k的公共前缀即可
for(int j=i;j<len&&H[j]>=k;j++) // 注意这里必须是连续的
if((suff[i-1]+k==suff[j]||suff[j]+k==suff[i-1]))
return true;
}
return false;
}
int main()
{
freopen("data.in","r",stdin);
scanf("%d",&test);
while(test--)
{
scanf("%s",str);
len=strlen(str);
for(int i=0;i<len;i++)
r[i]=str[i];
CreatSuff(150);
CalHeight();
int k;
for(k=len/2;k>=0;k--) //枚举K值
if(Check(k))
break;
printf("%d/n",k);
}
// while(1);
return 0;
}