【KMP】 HRBUST 2060 截取方案数

截取方案数

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;
}

猜你喜欢

转载自blog.csdn.net/peng0614/article/details/80150160
kmp