截取方案数
Time Limit: 1000 MS Memory Limit: 32768 K
Description
给定一个模式串T,主串S,问:从S中截取T有多少种方案?
Input
有多组测试数据,对于每组测试数据,第一行是模式串T,第二行是主串S,数据中仅包含大小写字母和数字,模式串T长度不超过10^4, 主串S长度不超过10^5。
注意:数据是随机的。
Output
对于每组测试数据,输出一行,为截取方案数。
Sample Input
abc
abcdaabcab
abcd
abcdaabcab
aba
abababa
Sample Output
2
1
3
Source
HCPC2014校赛训练赛 3
题意
在一个字符串中查找包含了多少个模式串。
思路
简单KMP应用。
对主串来一遍KMP,查找到一个模式串就ans++一下,处理完整个主串就好。
没找到一个字符串之后不返回坐标地址,而是清空k的信息并且将i定位的到当前位置,之后循环会将i再++。
if(k==plen-1){
k = -1;
ans++;
i = i - plen + 1;
}
对于KMP有疑惑的可以看一下下面的视频和博客:
【soso字幕】汪都能听懂的KMP字符串匹配算法【双语字幕】
KMP算法最浅显理解——一看就明白
坑点
数组开小了可能会RE
虽然我觉得我一开始开的足够大……
AC代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 100006
int nt[maxn];
char ptr[maxn];
char str[1000006];
int ans;
int plen;
int slen;
/*next数组构建一般操作*/
void get_next(void)
{
nt[0] = -1;
int k = -1;
for(int i = 1 ; i < plen ; i++)
{
while(ptr[i]!=ptr[k+1]&&k > -1) k = nt[k];
if(ptr[i]==ptr[k+1]) k++;
nt[i] = k;
}
}
/*kmp一般操作*/
void kmp(void)
{
int k = -1;
get_next();
for(int i = 0 ; i < slen ; i++)
{
while(str[i]!=ptr[k+1]&&k>-1) k = nt[k];
if(str[i]==ptr[k+1]) k++;
if(k==plen-1){
k = -1;
ans++;
i = i - plen + 1;///回溯
}
}
}
void solve(void)
{
while(~scanf("%s%s",ptr,str))
{
ans = 0;
plen = strlen(ptr);
slen = strlen(str);
kmp();
cout<<ans<<endl;
}
}
int main(void)
{
solve();
return 0;
}