两道水题飘过,表示KMP可以看严蔚敏教授的C语言视频
http://acm.hdu.edu.cn/showproblem.php?pid=1686
分析:找一个字符串中有几个另一个字符串(但在子串在匹配串可以覆盖)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=1000005;
int next[NM],ans;
char str1[NM],str2[NM];
void get_next(int len,char *s){
int i,j;
i=0;next[0]=j=-1;
while(i<len){
if(j==-1 || s[i]==s[j]){
i++;j++;next[i]=j;
}
else j=next[j];
}
}
void kmp(int len1,int len2,char *s1,char *s2){
int i,j;
get_next(len1,s1);
i=j=0;
while(i<len2){
if(j==-1 || s1[j]==s2[i]){
i++;j++;
}
else j=next[j];
if(j==len1){
j=next[j];ans++;
}
}
}
int main()
{
int T,len1,len2;
scanf("%d",&T);
while(T--){
scanf("%s%s",str1,str2);
len1=strlen(str1);
len2=strlen(str2);
if(len1>len2){
printf("0\n");continue;
}
ans=0;
kmp(len1,len2,str1,str2);
printf("%d\n",ans);
}
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=2203
分析:循环字符串什么的(小样儿),就在字符串尾再添一个原字符串就OK了
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int NM=100005;
int next[NM],ans;
char str1[NM<<1],str2[NM];
void get_next(int len,char *s){
int i,j;
i=0;next[0]=j=-1;
while(i<len){
if(j==-1 || s[i]==s[j]){
i++;j++;next[i]=j;
}
else j=next[j];
}
}
bool kmp(int len1,int len2,char *s1,char *s2){
int i,j;
get_next(len1,s1);
i=j=0;
while(i<len2){
if(j==-1 || s1[j]==s2[i]){
i++;j++;
}
else j=next[j];
if(j==len1) return true;
}
return false;
}
int main()
{
int len1,len2;
while(~scanf("%s",str2)){
len1=strlen(str2);
strcpy(str1,str2);
strcat(str1,str2);
scanf("%s",str2);
len2=strlen(str2);
if(len1<len2){
printf("no\n");continue;
}
len1+=len1;
if(kmp(len2,len1,str2,str1)) printf("yes\n");
else printf("no\n");
}
return 0;
}