输入
第一行一个整数N,表示测试数据组数。
接下来的N*2行,每两行表示一个测试数据。在每一个测试数据中,第一行为模式串,由不超过10^4个大写字母组成,第二行为原串,由不超过10^6个大写字母组成。
其中N<=20
输出
对于每一个测试数据,按照它们在输入中出现的顺序输出一行Ans,表示模式串在原串中出现的次数。
样例输入
5
HA
HAHAHA
WQN
WQN
ADA
ADADADA
BABABB
BABABABABABABABABB
DAD
ADDAADAADDAAADAAD
样例输出
3
1
3
1
0
思路:
KMP模板题,这篇博客讲的比较细https://www.cnblogs.com/yjiyjige/p/3263858.html
这里主要说一下如何理解next数组,next数组主要是对于模式串而言的,且除了当前字符之外的子串的前缀和后缀的匹配的字符个数。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e6;
int Next[maxn]; //next数组的含义是,除开当前字符外(在kmp中表示字符失配的那个位置),子串的前缀和后缀相同字符的个数。
void getNext(string p)
{
int len = p.length();
Next[0] = -1;
int k = -1;
int j = 0;
while(j < len ) {
if (k == -1 || p[j] == p[k]) { //p[k]表示前缀,p[j]表示后缀
Next[++j] = ++k;
}
else {
k = Next[k];
}
}
}
int kmp(string s, string p)
{
int i = 0;
int j = 0;
int res = 0;
int slen = s.length();
int plen = p.length();
getNext(p);
while(i < slen) {
while( j != -1 && p[j] != s[i]) j = Next[j];
++i;
++j;
if (j == plen) ++res;
}
//cout << i << " " << j << endl;
// if (j == plen) {
// //return i - j;
// return i;
// }
// else {
// return -1;
// }
return res;
}
int main()
{
string s,p;
int n;
cin >> n;
while(n--) {
memset(Next,0,sizeof(Next));
cin >> p >> s;
int res = kmp(s,p);
cout << res << endl;
}
return 0;
}