求多个字符串的最长公共子串
思路:
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; }