文章目录
- 题目描述
- 解析
- 代码
题目描述
解析
我的做法是二分答案,暴力枚举子串,对其他的字符串进行KMP。
复杂度logL*L2
没有一次AC,因为忘记了字符串清零!,否则它会和上次二分的字符串没被覆盖到的部分连在一起。
之前遇到过类似的问题了,没有引起重视,需要注意一下
做完后看了下题解,其实不用二分答案,用最短串枚举起点,对其他串进行KMP匹配,记录最大的失配位置就可以了,复杂度比我的做法少一个log
代码
(还是带log的做法。。。)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
typedef unsigned long long ull;
const int N = 2504;
const int M=1e7+5;
const int mod=1e7+3;
int n,m;
int l0[6],l;
char ss[6][N],s[N];
int p[N];
void solve(){p[1]=0;l=strlen(s+1);for(int i=1,j=0;i<=l;i++){while(s[i+1]!=s[j+1]&&j) j=p[j];if(s[i+1]==s[j+1]) j++;p[i+1]=j;}
}
bool kmp(int k){for(int i=0,j=0;i<=l0[k];i++){while(ss[k][i+1]!=s[j+1]&&j) j=p[j];if(ss[k][i+1]==s[j+1]) j++;if(j==l){return true;}}return false;
}
bool check(int k){//printf("check: %d\n",k);for(int i=1;i+k-1<=l0[1];i++){//memset(s,0,sizeof(s));for(int j=1;j<=k;j++){s[j]=ss[1][i+j-1];}//printf(" s=%s\n",s+1);solve();int flag=1;for(int j=2;j<=n;j++){if(!kmp(j)){//printf("j=%d not!\n",j);flag=0;break;}}if(flag) return true;}return false;
}
int main(){scanf("%d",&n);int st=0,ed=2000;for(int i=1;i<=n;i++){scanf(" %s",ss[i]+1);l0[i]=strlen(ss[i]+1);ed=min(ed,l0[i]);}while(st<ed){int mid=(st+ed+1)>>1;if(check(mid)) st=mid;else ed=mid-1;}printf("%d",st);return 0;
}
/*
3
abdcdjjjds
ajjsnbadcd
cdjjsdcdda
*/