代码改变世界

KMP hihoCoder1015 KMP算法

2017-05-12 08:03  tlnshuju  阅读(201)  评论(0编辑  收藏  举报

人太蠢,,看了一天的KMP。。

刚開始看训练指南的,,后来才惊奇的发现原来刘汝佳写的f数组并非Next数组!

总认为和之前看过的全然不一样。。

后来又百度了一下KMP,研究了非常久,然后用自己的逻辑写了一份


http://blog.chinaunix.net/uid-23767307-id-5033555.html

这个人把KMP大篇幅的讲了。。大家能够看看。

个人觉得仅仅要能理解Next数组的意义后,写出KMP算法就不是非常难了

然而自己语文也不好就不多做解释了,,直接贴下我的模板好了

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;

const int MX = 1e6 + 5;

char S1[MX], S2[MX];
int Next[MX];

int KMP(char *A, char *B) {
    int m = strlen(A), n = strlen(B);

    Next[0] = 0;
    for(int i = 1; i < n; i++) {
        int k = Next[i - 1];
        while(B[i] != B[k] && k) k = Next[k - 1];
        Next[i] = B[i] == B[k] ? k + 1 : 0;
    }

    int ans = 0, j = 0;
    for(int i = 0; i < m; i++) {
        while(A[i] != B[j] && j) j = Next[j - 1];
        if(A[i] == B[j]) j++;
        if(j == n) ans++;
    }
    return ans;
}

int main() {
    int T, ansk = 0;
    //freopen("input.txt", "r", stdin);
    scanf("%d", &T);
    while(T--) {
        scanf("%s%s", S1, S2);
        printf("%d\n", KMP(S2, S1));
    }
    return 0;
}
当中,假设想函数返回的是出现的次数,而不是匹配的次数

由于匹配的次数中会有一些部分是重叠的。那仅仅要改一个地方即可了

把if(j == n) ans++;换成if(j == n) ans++, j = 0;就能够了

int KMP(char *A, char *B) {//A是被搜索的串,B是搜索的内容,返回B在A中出现的次数
    int m = strlen(A), n = strlen(B);

    Next[0] = 0;
    for(int i = 1; i < n; i++) {
        int k = Next[i - 1];
        while(B[i] != B[k] && k) k = Next[k - 1];
        Next[i] = B[i] == B[k] ? k + 1 : 0;
    }

    int ans = 0, j = 0;
    for(int i = 0; i < m; i++) {
        while(A[i] != B[j] && j) j = Next[j - 1];
        if(A[i] == B[j]) j++;
        if(j == n) ans++, j = 0;
    }
    return ans;
}