Hihocoder 1625 : 重复字符串匹配 (KMP)
描述
给定两个字符串A和B,请你求出字符串A最少重复几次才能使得B是A的子串。
例如A="hiho",B="hohihohi"。则A重复3次之后变为"hihohihohiho",这时B是A的子串。
输入
输入包含多组数据。
第一行包含一个整数T,表示数据组数。 (1 ≤ T ≤ 5)
对于每组数据,第一行包含一个字符串A,第二行包含一个字符串B。
对于30%的数据,1 ≤ |A|, |B| ≤ 1000
对于100%的数据, 1 ≤ |A|, |B| ≤ 100000 并且A和B都只包含小写字母。
输出
A最少重复的次数。如果无论重复多少次也不能包含B,输出-1。
样例输入
2 hiho hohihohi hiho coder
样例输出
3 -1
思路:一直重复A字符串(有上限),看是否可以达到k==lenb。
没必要枚举起点,一位任何一位A[i]都可以做起点,所以最多多加一个循环。 即次数不超过 ((lenb-1)/lena+1) +1 。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=1000010; int Next[maxn],ans; char a[maxn],b[maxn]; void kmp() { int k=0,lena=strlen(a+1),lenb=strlen(b+1); ans=-1; Next[1]=0; for(int i=2;i<=lenb;i++){ while(k&&b[i]!=b[k+1]) k=Next[k]; if(b[i]==b[k+1]) k++; Next[i]=k; } k=0; for(int p=1;p<=(lenb-1)/lena+2;p++){ for(int i=1;i<=lena;i++){ while(k&&a[i]!=b[k+1]) k=Next[k]; if(a[i]==b[k+1]) k++; if(k==lenb) { ans=p; return ;} } } } int main() { int T; scanf("%d",&T); while(T--){ memset(Next,0,sizeof(Next)); scanf("%s%s",a+1,b+1); kmp(); printf("%d\n",ans); } return 0; }
It is your time to fight!