Data Structure Notes--Implementation of KMP Algorithm

1--principle

Video explanation reference: the most easy-to-understand KMP algorithm explanation 

Principle explanation reference: KMP algorithm detailed explanation 

2--code

C++:

#include <vector>
#include <string>
#include <iostream>

class KMP{
public:
    int kmp_search(std::string String, std::string Patt){
        build_next(Patt); // 构建next数组
        int i = 0;
        int j = 0;
        while(i < String.length()){
            if(String[i] == Patt[j]){
                i += 1;
                j += 1;
            }
            else if(j > 0){
                j = next[j - 1];
            }
            else{
                i += 1;
            }
            if (j == Patt.length()){
                return i - j;
            }
        }
        return -1;
    }

    void build_next(std::string Patt){
        next.push_back(0); // 第0个字符的next数组为0
        int j = 0; // 从第0个字符开始
        int i = 1; // 从第一个字符开始遍历
        while (i < Patt.length()){
            if (Patt[j] == Patt[i]){
                j += 1;
                i += 1;
                next.push_back(j);
            }
            else{
                if (j == 0){
                    next.push_back(0);
                    i += 1;
                }
                else{
                    j = next[j - 1];
                }
            }
        }
    }

private:
    std::vector<int> next; // next数组
};

int main(int argc, char* argv[]){
    std::string String = "ababcbc";
    std::string Patt = "abcb";
    KMP Solution;
    int pos = Solution.kmp_search(String, Patt);
    std::cout << "Position: " << pos << std::endl;
    return 0;
}

python:

# Test KMP Algorithm

def build_next(patt): # 对子串构建其next数组
    next = [0] # 第0个字符的next数组为0
    j = 0 # 从第0个字符开始
    i = 1 # 从第1个字符开始遍历
    while i < len(patt):
        if patt[j] == patt[i]: # 当前字符i与字符j相同
            j += 1 # 右移
            i += 1 # 右移
            next.append(j) # 用j表示当前字符i的相同前后缀长度
        else: # 当前字符i与字符j不相同
            if j == 0:  # 如果字符j已经是第0个字符
                next.append(0) # 则当前字符i的相同前后缀长度为0
                i += 1 # 比较下一个字符
            else: # 如果字符j不是第0个字符
                j = next[j - 1] # 比较字符j前一个字符j-1的next数组对应位置的字符
    return next 

def kmp_search(string, patt): # string主串 patt待匹配的子串
    next = build_next(patt)
    i = 0
    j = 0
    while i < len(string):
        if string[i] == patt[j]: # 字符匹配,右移下一位
            i += 1
            j += 1
        elif j > 0: # 字符不匹配, j回退并跳过字符
            j = next[j - 1] # 跳过的字符取决于前一个字符对应的next数组
        else: # 字符不匹配, j已经处在子串第一个字符中
            i += 1 # 从主串下一个字符开始匹配
        if j == len(patt): # 表明子串的所有字符都匹配成功
            return i - j # 返回匹配主串的第一个字符位置

if __name__ == "__main__":
    string = "ababcbc"
    patt = "abcb"

    index = kmp_search(string, patt)
    print("start_index: ", index)

Guess you like

Origin blog.csdn.net/weixin_43863869/article/details/131032738