【数据结构】KMP算法


目录

KMP时间复杂度 

match函数

match的实现

match的时间复杂度

具体代码实现:



KMP要求模式串一头一尾能匹配上

 

解释: j=6时候,match = 3,意思是p0-p3是能够和p(6-3)-p6匹配。


注意:当有一个串能配得上,并不能到此为止,要继续检查还有没有更长的串。

KMP时间复杂度 

match函数

 

优秀的做法:

首先j-1位置和match【j-1】位置匹配

然后考虑j位置和match[j-1]+1位置是否匹配?如果匹配

如果match[j]>match[j-1]+1,考虑向前一个位置A

如果能匹配,则后面字符都能匹配。

一旦出现这种情况,意味着A-X能匹配上,意味着对于0到j-1这个子串来说他的macth值应该指向X,match[j-1]+1的位置。这是不可能的。用反证法证明:

                                                          match[j] = match[j-1]+1

当j位置和match[j-1]+1不匹配,查看前match[j-1]是否有匹配的

递归的查看

比较两个?的位置,即比较j和match[match[j-1]] +1(回溯)

如果能够匹配

match[match[j - 1]] +1 = match[j]

match的实现

match的时间复杂度

O(m)平方是上界

 

具体代码实现:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

vector<int> buildMatch(string p) {
    int len = p.size(), k = -1, j = 0;//k表示和j匹配,也表示匹配从0到k 
    vector<int> match(len, -1);//初始化为-1

    while (j < len - 1) {
        if (k == -1 || p[j] == p[k]) {
            ++k; ++j;
            match[j] = (p[j] != p[k]) ? k : match[k];//要避免出现p[j] == p[match[j]]的情况
        } else {
            k = match[k];
        }
    }
    return match;
}

int kmp(string s, string p) {
    int m = s.size(), n = p.size();
    if(m < n) return -1;
    
    vector<int> match = buildMatch(p);
    int i = 0, j = 0;
   
    while (i < m && j < n) {
        if (j == - 1 || s[i] == p[j]) {
            ++i; ++j;
        } else {
            j = match[j];
        }
    }
    return (j == n) ? i - j : -1;
}

int main() {
	string s,p;
	cin>>s>>p;
    cout << kmp(s, p) << endl;  
}

 

参考:https://www.bilibili.com/video/BV1zJ411E7cg?p=146

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章