Problem B: #103. 子串查找
Time Limit: 5 Sec Memory Limit: 256 MB
Submit: 110 Solved: 44
[Submit][Status][Web Board]
Description
这是一道模板题。
给定一个字符串 A 和一个字符串 B,求 B 在 A 中的出现次数。
A 中不同位置出现的 B 可重叠。
Input
输入共两行,分别是字符串 A 和字符串 B。
Output
输出一个整数,表示 B 在 A 中的出现次数。
Sample Input
zyzyzyz
zyz
Sample Output
3
HINT
1≤A,B 的长度 ≤106 ,A 、B 仅包含大小写字母。
[分析]
很水的题目但是非常的暴露基础。错了好几次。
中间tle一次,然后突然参悟正确的计数方法。(其实还是很开心的)
不过发现,strstr效率没有手写的kmp高,很难受,strstr做5000+ms,kmp20ms。
[strstr代码]
#include<cstdio>
#include<cstring>
int main()
{
char a[10000000];
char b[10000000];
while (scanf("%s%s", a, b) != EOF)
{
char *p = a-1;
int ans = 0;
while (*(p + 1) != '\0' && (p = strstr(p + 1, b)) != NULL)
{
ans++;
}
out:;
printf("%d\n", ans);
}
}
[KMP代码]
#include <iostream>
#include <cstdio>
#include <cstring>
const int maxn=1000000+10;
using namespace std;
char pstring[maxn],tstring[maxn];
int plength,tlength;
int next[maxn];
long long ans=0;
void getnext(){
int i,j;
next[0]=-1;
i=0;
j=-1;
while(i<plength)
{
if(j==-1||pstring[i]==pstring[j]){
i++;j++;next[i]=j;
}
else
j=next[j];
}
}
int kmp(int pos)
{
int i,j;
i=pos;j=0;
while(i<tlength){
if(j==-1||tstring[i]==pstring[j]){
i++;j++;
}
else
j=next[j];
if(j==plength)
ans++;
}
}
int main(){
while(~scanf("%s\n%s",tstring,pstring))
{
plength=strlen(pstring);
tlength=strlen(tstring);
ans=0;
if(plength<=tlength)
{
getnext();
kmp(0);
}
printf("%lld\n",ans);
}
return 0;
}
[后记]
刚刚查了一下,在网上找了一个解释。
像一般文本找子串strstr是比较快的,像aaaaaaaaaaaaaaaaa找aaaaaaaaaaaaaaaaaaab这种骚数据,KMP是比较快的。所以在OJ上,KMP效率更高。