题意:
求多个字符串的最长公共子串
思路:
4000个串,200长度。
一种暴力,对于一个串最多有200*200=40000级别个子串,然后我要再处理一下next数组200,8e6复杂度;
然后我要和4000个串去匹配一下,看看符不符合,400000*4000*200这样就炸了;
其实显然不需要所有的子串都枚举出来,可以二分来搞,因为显然如果有aaaa为最长公共字串,则aaa则一定有。
然后参考了一篇博文,用KMP,是利用其快速求最长前缀,所以只需要枚举开头即最多200/2=100次。复杂度才O(4000*100)
这份代码的GetlongestPre函数中,逐渐缩短模式串也有贪心的意思。
看自己理解吧。
//#include<bits/stdc++.h>
//using namespace std;
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std; const int N=4e3+10;
const int M=2e2+10; char wxy[N][M];
int next[M],n; void GetNext(char *s,int len)
{
int i,j;
next[0]=-1;
i=0;
j=-1;
while(i<len)
{
if(j==-1||s[i]==s[j])
next[++i]=++j;
else
j=next[j];
}
} int GetLongestPre(char *s,int len)
{
GetNext(s,len);
for(int i=1; i<n; i++)
{
char *p=wxy[i];
int j=0,tmp=0;
while(*p&&j<len)
{
if(j==-1||*p==s[j])
{
p++;
j++;
tmp=max(tmp,j);
}
else
j=next[j];
}
len=tmp;
}
return len;
} int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=0; i<n; i++)
scanf("%s",wxy[i]); int len=strlen(wxy[0]);
int ans=0,biginpos=0;
for(int i=0; i<len; i++)
{
int tmp=GetLongestPre(wxy[0]+i,len-i);
if(tmp>=ans)
{
if(tmp>ans)
{
ans=tmp;
biginpos=i;
}
else
{
bool flag=true;
for(int t=0; t<ans; t++)
{
if(wxy[0][biginpos+t] > wxy[0][i+t]) break;
else if(wxy[0][biginpos+t] < wxy[0][i+t])
{
flag=false;
break;
}
}
if(flag)
biginpos=i;
}
}
}
if(ans)
for(int i=0; i<ans; i++)
printf("%c",wxy[0][biginpos+i]);
else
printf("IDENTITY LOST");
puts("");
}
return 0;
}