给一个字符串S,问是否存在一个子串s'同时为s的前缀,后缀,并且至少出现在前缀后缀之外的位置一次(互不重叠)。10^6的数据...一开始想写后缀数组,看这数据估计是要卡倍增,DC3又没写过..后来想了想直接KMP扫一遍好像就行..以末尾为起点,遍历从失配路径上的每一个点,如果f[j]小于len/3,那么就从2*f[j]+1~len-f[len] 之间枚举k看是否存在f[k]==f[j],存在的话答案就是f[j]。 刚开始我是从f[j]+1开始枚举的,但是遇到aaaabkaa的时候,找出来的答案是3,事实上结果应该是2..不得不吐槽数据给的还是有点弱了- =....
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
const int maxn=1000000+100;
char str[maxn],s[maxn],s1[maxn];
int f[maxn];
void getFail(char* P,int* f)
{
int m=strlen(P);
f[0]=0;
f[1]=0;
for (int i=1; i<m; i++)
{
int j=f[i];
while(j && P[i]!=P[j]) j=f[j];
f[i+1]=P[i]==P[j]?j+1:0;
}
}
int find(char* T,char* P,int* f)
{
int n=strlen(T);
int m=strlen(P);
getFail(P,f);
int j=0;
for (int i=0; i<n; i++)
{
while(j && P[j]!=T[i]) j=f[j];
if (P[j]==T[i]) j++;
if (j==m) return i-m+1;
}
}
int main()
{
// freopen("in.txt","r",stdin);
int tt,len;
scanf("%d",&tt);
while(tt--)
{
scanf("%s\n",s);
getFail(s,f);
len=strlen(s);
int pt=len;
int ans=0;
while(true)
{
if (pt>(len/3))
{
pt=f[pt];
continue;
}
for (int i=pt+pt-1; i<=len-pt; i++)
{
if (f[i]==pt)
{
ans=pt;
break;
}
}
if (ans) break;
if (pt==0) break;
pt=f[pt];
}
printf("%d\n",ans);
}
return 0;
}