KMP算法解决字符串匹配

该算法由D.E.Knuth ,J.H.Morris和 V.R.Pratt提出,用于解决字符串匹配问题。

思想:

设目标串(主串)为s,模式串为t ,并设i指针和j指针分别指示目标串和模式串中正待比较的字符,设i和j的初值均为0。若有s[i]=t[j],则i和j分别加1。否则,i不变,j退回到j=next[j-1]的位置,再比较s[i]和t[j],若相等,则i和j分别加1。否则,i不变,j再次退回到j=next[j]的位置,依此类推。直到下列两种可能:
1. 模式串t中的字符全部匹配,则出现频率+1
2. 退回到j=0,将i加1,即从主串的下一个字符s[i+1]与模式串t[0]处重新开始匹配。

什么是next数组?

next数组是对模式串t中各元素位置下的一种历史信息记录。它的数学定义为:
next[i] = max{0<=k<=i|t.substring(0,k) == t.substring(i-k+1,k)}
其中:t.substring(i,k)表示t从索引i开始的k个字符的子串。
例如模式串t:bababb,其next数组为{0,0,1,2,3,1}.

如何求next数组?

求解next数组其实也是利用kmp思想。初始时next[0]=0.
对于next[i],我们将t.substring(0,i+1)作为目标串,将t.substring(0,i)作为模式串,根据q =next[i-1],只要有t[i]==t[q],则next[i] = q+1;否则q = next[q-1]继续类推,直到退回到q=0,此时表示next[i]=0.

题目

#1015 : KMP算法

输入

第一行一个整数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

代码

#include<stdio.h>
#include<string.h>
#define S_LEN 1000005
#define T_LEN 10005

char t[T_LEN];
char s[S_LEN];

int next[T_LEN];

//求解next数组
void solve_next(){
    int t_len = strlen(t);
    memset(next, 0, t_len*sizeof(int));
    int p,q;
    for (p = 1; p < t_len; p++){
        q = next[p - 1];
        while (1){
            if (t[p] == t[q]) {
                next[p] = q + 1; break;
            }
            if (!q) break;
            q = next[q - 1];
        }
    }
}

//查找匹配
int kmp() {
    int t_len = strlen(t);
    int s_len = strlen(s);
    if (t_len > s_len) return 0;
    int ans = 0, i = 0, j = 0;
    while (j < s_len){
        while (i < t_len&&j < s_len && t[i] == s[j]) {
            i++; j++;
        }
        if (i == t_len) ans++;
        if (!i) j++; 
        else i = next[i - 1];
    }
    return ans;
}

int main(void){
    int N,i;
    scanf("%d", &N);
    for (i = 0; i < N; i++){
        scanf("%s%s", t, s);
        solve_next(); 
        printf("%d\n", kmp());
    }
    return 0;
}
结果语言时间内存
ACGCC46ms7MB
    原文作者:KMP算法
    原文地址: https://blog.csdn.net/barry283049/article/details/48035231
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞