题意:
给出串W, T,计算串 W 在串 T 中出现了多少次?
数据范围:
1 < = ∣ W ∣ < = 1 0 4 , ∣ W ∣ < = ∣ N ∣ < = 1 0 6 1<=|W|<=10^4, |W|<=|N|<=10^6 1<=∣W∣<=104,∣W∣<=∣N∣<=106
思路:
- 要求重复匹配,即在裸 KMP 的基础上,问如果到达串 W 匹配到末尾了怎么办?
- 如果串 W 匹配到末尾,则计数,把 位置 j 当做失配处理 ,继续匹配,直到 i 一直匹配到末尾over。(区别于
HDU2087 剪花布条
,当模式串匹配到末尾时,必须从头开始匹配,j 要置为 0 ,因为前面匹配到的已经剪掉了)
input:
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN
output:
1
3
0
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int M=1e4+10;
const int N=1e6+10;
char text[N],pattern[M];
int len_w,len_t,nxt[M];
void get_next()
{
int i = 0, j = -1;
nxt[0] = -1;
while(i < len_w)
{
if(j == -1 || pattern[i] == pattern[j])
{
i++;
j++;
nxt[i] = j;
}
else
j = nxt[j];
}
}
int kmp()
{
get_next();
int i = 0, j = 0;
int cnt = 0;
while(i < len_t) // 结束的条件是 串 T 到达末尾
{
if(j == -1 || text[i] == pattern[j])
{
i++;
j++;
if(j == len_w) //如果串 W 匹配到末尾,则计数,把 位置j 当做失配处理
{
cnt++;
j = nxt[j];
}
}
else
j = nxt[j];
}
return cnt;
}
int main()
{
int t,ans;
cin>>t;
while(t--)
{
memset(nxt, 0, sizeof nxt);
scanf("%s %s", pattern, text);
len_w = strlen(pattern);
len_t = strlen(text);
ans = kmp();
printf("%d\n", ans);
}
return 0;
}