hihocoder KMP算法

来源:互联网 发布:口语培训班知乎 编辑:程序博客网 时间:2024/06/05 03:33

offer算法合集收割

KMP Next数组详解(这篇算是写的比较清晰)

题意:

就是求一个字符串在另一个字符串中出现的次数;

理解:

直接上KMP的模板;

对KMP理解:

KMP的重点是求Next数组;
但是为什么要求Next数组呢?
原因是在失配的情况下;
当前字符之前的字符串是否有相同的前后缀
如果有,那么就可以移动相同前后缀的长度来继续匹配;
这样便不需要再从第一个字符开始匹配;
当然这样也有可能直接匹配失败;
那么此时就在这个子串的前面再找个相同的前后缀,依次类推;
如果没有,那么在向前回到起始位置;
最坏情况就是回到第一个位置;

那么Next数组和这个前后缀的关系是什么呢?
Next数组表明下一次我们应该从哪一个开始匹配;
这个意思就是Next数组便是存储了通过前后缀得出的相对位移

那么这个相对位移怎么求呢?
这个过程我也只能从代码上看出来;
但是道理就是对的;

代码如下:

#include <cstdio>#include <cstring>#include <cmath>#include <ctime>#include <iostream>#include <algorithm>#include <vector>#include <string>#include <map>#include <set>#include <queue>#include <stack>using namespace std;typedef long long LL;typedef pair<int, int> PII;const double MIN_INF = 1e-7;const int MAX_INF = (1e9) + 7;#define X first#define Y secondvoid getNext(vector<int> &Next, string &str2) {    Next[0] = -1;    int i = 0, j = -1;    int S_2 = str2.length();    while (i < S_2) {        if (j == -1 || str2[i] == str2[j]) {//此处便是在匹配最长前后缀            ++i;            ++j;            Next[i] = j;        }        else {            j = Next[j];//而这个就是通过先前求过的前后缀来求下一个前后缀        }    }}int kmp(string &str1, string &str2) {    int ans = 0;    vector<int> Next(str2.size() + 10000);    getNext(Next, str2);    int i = -1, j = -1;    int S_1 = str1.length(), S_2 = str2.length();    while (i < S_1) {        if (j == -1 || str1[i] == str2[j]) {            ++i;            ++j;        }        else {            j = Next[j];        }        if (j == S_2) {            ++ans;        }    }    return ans;}int main() {    int t;    cin >> t;    while (t--) {        string str1, str2;        cin >> str2 >> str1;        cout << kmp(str1, str2) << endl;    }    return 0;}
0 0
原创粉丝点击