5 xy abc aaa aaaaba aaxoaaaaa
0 0 1 1 2
问给定字符串可否划分出三个相同子串 第一个以母串首字符开始 最后一个以母串结尾字符结束 中间的在母串中 三个串不可重叠
相同子串 能联想到KMP的前缀方法(从当前字符的next数组指向的位置往前到母串首 和 从当前字符向前相同长度的串是相同串)
三串不好想 如果两串呢
首尾找最长相同两串我的思路是找出最后一个字母不断next过程中经过的下标 下标>母串长len/2 的话肯定不行 <len/2 的最大的就是所求长度(一定满足 因为是从母串中心分开的 必定不重叠
三串可以用同样思路 找小于len/3的 这样前后都满足了相同且不重叠 但中间串呢 上STL吧……或者用自己做好的KMP也行 图省事。。只要找到当前坐标往前的串在当前坐标往后的串中第一次出现的位置 看是否在当前坐标x*2~len-x之间即可
代码如下:
#include <bits/stdc++.h>
using namespace std;
char str[1111111];
int Next[1111111];
void GetNext()
{
Next[0] = -1;
int k,len;
len = strlen(str);
for(int i = 1; i < len; ++i)
{
k = Next[i-1];
while(k != -1 && str[k+1] != str[i]) k = Next[k];
if(k == -1 && str[0] != str[i]) Next[i] = -1;
else if(k == -1 && str[0] == str[i]) Next[i] = 0;
else Next[i] = k+1;
}
}
int num[1111111],tp;
int main()
{
int n,m,t,i,j,u,v,w,len,k,mm,mlen,l,r;
int pos;
scanf("%d",&t);
while(t--)
{
scanf("%s",str);
GetNext();
len = strlen(str);
tp = 0;
num[tp++] = len;
k = Next[len-1];
while(k != -1)
{
num[tp++] = k+1;
k = Next[k];
}
sort(num,num+tp);
mm = -1;
for(i = 0; num[i] <= len/3; ++i)
{
if(mm == -1 || num[mm] < num[i]) mm = i;
}
while(mm != -1)
{
l = strstr(str+num[mm],str+len-num[mm])-str;
if(l >= num[mm] && l+num[mm] <= len-num[mm]) break;
--mm;
}
if(mm == -1) puts("0");
else printf("%d\n",num[mm]);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
【HDOJ 4763】 Theme Section (KMP+strstr)
原文:http://blog.csdn.net/challengerrumble/article/details/48263969