zoukankan      html  css  js  c++  java
  • 两种常见的模式匹配算法(代码实现)

    BF算法(暴力法)

    不多解释,直接上代码:

    // BF算法 O(mn)
    int bf(SString s, SString t, int pos){
        int i = pos, j = 0;
        while (i < s.length && j < t.length){
            if (s.ch[i] == t.ch[j]){
                i++;
                j++;
            } else {
                i = i - j + 1;
                j = 0;
            }
        }
        if (j >= t.length) 
            return i - t.length;
        else 
            return -1;
    } 
    
    // 另一个版本的BF算法 - O(mn) 
    int pm(SString s, SString t, int pos){
        for (int i = pos; i <= s.length-t.length; i++){
            bool status = true;
            for (int j = 0; j < t.length; j++){
                if (s.ch[i+j] != t.ch[j]){
                    status = false;
                    break;
                }
            }
            if (status)
                return i;
        }
        return -1;
    } 
    

    KMP算法

    KMP算法较难理解,在大二上数据结构这门课的时候就没有搞懂,今天花了点时间终于把它看懂了。

    KMP算法相比BF算法,其改进主要在使用了一个前后缀匹配数组next(我自己起的名儿~)来记录前缀和后缀的匹配信息,以使得在发现主串与模式串的比较中出现不匹配时,主串指针无需回溯,并根据前后缀匹配数组中的信息,向后移动,从而减少了多余的比较。

    代码实现:

    // KMP算法
    int kmp(SString &s, SString &t, int pos){
        int next[t.length], j = 0, i = 0;
        get_next(t, next);
        
        while (i < s.length && j < t.length){
            if (j == -1 || s.ch[i] == t.ch[j]){
                i++; j++;
            } else 
                j = next[j];
        }
        if (j >= t.length)
            return i-t.length;
        else 
            return -1;
    }
    
    
    void get_next(SString &t, int next[]){
        int i = 0, j = -1;
        next[0] = -1;
        while (i < t.length - 1){
            if (j == -1 || t.ch[i] == t.ch[j]){
                i++; j++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    } 
    

    参考博客:

    可运行的整体代码:

    #include<iostream>
    #define MAXLEN 100
    #define CHUNKSIZE 50
    
    using namespace std;
    
    // 串的普通顺序存储
    typedef struct {
        char ch[MAXLEN+1];
        int length;
    }SString; 
    
    // 串的堆式顺序存储 
    //typedef struct {
    //    char *ch;
    //    int length;
    //}SString;
    
    // 串的链式存储
    typedef struct chunk{
        char ch[CHUNKSIZE];
        struct chunk *next;
    }Chunk;
    
    typedef struct {
        Chunk *head, *tail;
        int length;
    }LString; 
    
    // 普通顺序存储的初始化操作 
    void SsInit(SString &s){
        s.length = 0;
    }
    
    void SsInput(SString &s){
        char c;
        while ((c = getchar()) != '
    '){
            s.ch[s.length++] = c;
        }
    }
    
    void printString(SString &s){
        for (int i = 0; i < s.length; i++){
            cout << s.ch[i];
        }
        cout << endl;
    } 
    
    // BF算法 - O(mn) 
    int pm(SString s, SString t, int pos){
        for (int i = pos; i <= s.length-t.length; i++){
            bool status = true;
            for (int j = 0; j < t.length; j++){
                if (s.ch[i+j] != t.ch[j]){
                    status = false;
                    break;
                }
            }
            if (status)
                return i;
        }
        return -1;
    } 
    
    // 另一种版本的BF算法 O(mn) - 与暴力法相似 
    int bf(SString s, SString t, int pos){
        int i = pos, j = 0;
        while (i < s.length && j < t.length){
            if (s.ch[i] == t.ch[j]){
                i++;
                j++;
            } else {
                i = i - j + 1;
                j = 0;
            }
        }
        if (j >= t.length) 
            return i - t.length;
        else 
            return -1;
    } 
    
    // KMP算法
    int kmp(SString &s, SString &t, int pos){
        int next[t.length], j = 0, i = 0;
        get_next(t, next);
        
        while (i < s.length && j < t.length){
            if (j == -1 || s.ch[i] == t.ch[j]){
                i++; j++;
            } else 
                j = next[j];
        }
        if (j >= t.length)
            return i-t.length;
        else 
            return -1;
    }
    
    
    void get_next(SString &t, int next[]){
        int i = 0, j = -1;
        next[0] = -1;
        while (i < t.length - 1){
            if (j == -1 || t.ch[i] == t.ch[j]){
                i++; j++;
                next[i] = j;
            } else {
                j = next[j];
            }
        }
    } 
    
     
    int main(){
        SString s, t;
        SsInit(s);
        SsInput(s);
        SsInit(t);
        SsInput(t);
        
        int loc = -1; 
    //    loc = pm(s, t, 0);
    //    loc = bf(s, t, 0);
        loc = kmp(s, t, 0);
        
        cout << loc << endl;
    }
    
    
    
    CS专业在读,热爱编程。
    专业之外,喜欢阅读,尤爱哲学、金庸、马尔克斯。
  • 相关阅读:
    Docker之路-docker架构
    Docker之路-认识docker
    Docker之路-版本选择及安装
    Golang理解-集合
    大话算法-动态规划算法
    运维职责
    Golang理解-匿名结构体
    DotNetty项目基本了解和介绍
    变量声明在循环体内还是循环体外的争论
    SqlServer与MySql语法比较
  • 原文地址:https://www.cnblogs.com/jmhwsrr/p/14544704.html
Copyright © 2011-2022 走看看