hdu 1686 Oulipo (KMP)(计算模式串匹配的次数——与已匹配的字串可以有交集)

<题目链接>

题目大意:

输入一个T,表示有T组测试数据;

每组测试数据包括一个字符串W,T,T的长度$le10^6$,$W$的长度$le 10^4$,计算W匹配到T中成功的次数;

需要注意的是:

第一次将匹配成功的位置得到后,若从匹配到的位置开始算起,会超时,实际上没必要,每次模式串匹配成功时,都将个数+1,然后从next数组的下一位继续开始匹配,直至待匹配串结束

代码如下:实际上就是将kmp裸题稍微改一下。

若两个不同的匹配没有交集则j=0,若存在交集则j=next[j]

#include <bits/stdc++.h>
using namespace std;

const int N1 = 1e6+5, N2 = 1e4+5;
int nxt[N2];
char str1[N1],str2[N2];
int cnt;          //匹配的子串个数

inline void get_nxt(int len2){
    int i = 0, j = -1;
    nxt[0] = -1;
    while (i<len2){
        if (j == -1 || str2[i] == str2[j])nxt[++i]=++j;
        else j = nxt[j];
    }
}
inline void kmp(int len1, int len2){
    int i = 0, j = 0;
    get_nxt(len2);
    while (i<len1){
        if (j == -1 || str1[i] == str2[j])++i,++j;
        else j = nxt[j];
        if (j == len2)++cnt,j=nxt[j];                //找到一个匹配的串后,模式串的起点从nxt数组下一个点继续匹配    
    }
}
int main(){
    int n;scanf("%d", &n);getchar();
    int len1,len2;
    while (n--){
        gets(str2);gets(str1);
        len1 = strlen(str1);
        len2 = strlen(str2);
        cnt = 0;
        kmp(len1, len2);
        printf("%d
", cnt);
    }
}
原文地址:https://www.cnblogs.com/00isok/p/8871057.html