模式串匹配算法(樸素模式匹配算法和KMP算法)

模式串匹配算法,由之前的樸素模式算法延伸到KMP算法,效率上提升了將近一半。樸素模式算法上是將主串中的字符與子串中的字符一一比較,然後讓子串的字符不匹配的字符重新在從主串匹配完的部分匹配。這樣會導致一個問題就是子串不斷地回溯比較,效率低下。因而KMP算法誕生,就是改進了這一個問題。KMP算法是當匹配到不相同的字符時,將匹配下一個字符的位置交給了next數組。next數組的原理是最大字符前綴和最大字符後綴相等長度加一。大大的提高了效率。但是儘管KMP算法提高了效率,仍然有無意義的比較。因而改進KMP算法的next數組爲nextval數組,從左到右依次比較是否與之前的字符相同,若相同則將相同的next值賦值到相同的字符中,這樣就大大的節省了無意義的比較次數。
模式串匹配算法(樸素模式匹配算法和KMP算法)
下面看詳細代碼:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 255
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

/**
串的順序存儲和鏈式存儲 
由於C語言中有對串直接操作的函數,這隻列舉一種操作 
樸素模式匹配算法 
*/

//靜態定義串的結構體(定長順序存儲)
typedef struct{
    char ch[MaxSize];//存儲字符的數組 
    int length;//串的實際長度 
}SString; 

//動態方式定義串的結構體(爲了避免存儲密度低的問題,讓結點存儲多個字符) 
typedef struct StringNode{
    char ch[4];//每個結點放四個字符 
    struct StringNode *next;//指針域 
}StringNode,*String; 

//動態定義串的結構體(堆分配存儲)
typedef struct{
    char *ch;//按照串長分配儲存區,ch指向串的首地址 
    int length;//串的實際長度
}HString; 

//堆分配初始化
void InitHString(HString &S){
    S.ch = (char*)malloc(MaxSize*sizeof(char));
    S.length = 0;
} 

//求子串
bool SubString(SString &Sub,SString S,int pos,int len){
    //子串越界
    if(pos+len-1>S.length){
        return false;
    } 
    for(int i=pos;i<pos+len;i++){
        Sub.ch[i-pos+1] = S.ch[i];
    }
    Sub.length = len;
    return true;
}

//樸素模式匹配算法 
int Index(SString S,SString T){
    int k=1;
    int i=k,j=1;
    while(i<=S.length && j<=T.length){
        if(S.ch[i]==T.ch[j]){
            ++i;
            ++j;//繼續比較後續字符 
        }else{
            k++;//檢查下一個子串 
            i=k;
            j=1;
        }
    }
    if(j>T.length){
        return k;
    }else{
        return 0;
    }
}

//求模式串中next數組
void get_next(SString T,int next[]){
    int i = 0;
    int j = 0;
    next[1] = 0;
    while(i<T.length){
        if(j==0||T.ch[i]==T.ch[j]){
            ++i;
            ++j;
            //若pi=pj,則next[j+1]=next[j]+1 
            next[i] = j;
        }else{
            //否則循環繼續 
            j = next[j];
        }
    }
} 

//KMP算法2 
int IndexKMP(SString S,SString T){
    int i=1,j=1;
    int next[T.length+1];
    get_next(T,next);
    while(i<=S.length && j<=T.length){
        if(j==0||S.ch[i]==T.ch[j]){
            ++i;
            ++j;//繼續比較後續字符 
        }else{
            j=next[j];//模式串向右移動 
        }
    }
    if(j>T.length){
        return i-T.length;//匹配成功 
    }else{
        return 0;
    }
}

//KMP算法1
int Index(SString S,SString T,int next[]){
    int i=k,j=1;
    while(i<=S.length && j<=T.length){
        if(j==0 || S.ch[i]==T.ch[j]){
            ++i;
            ++j;//繼續比較後續字符 
        }else{
            j=next[j];
        }
    }
    if(j>T.length){
        return i-T.length;
    }else{
        return 0;
    }
} 

int main(int argc, char** argv) {
    HString S;
    InitHString(S);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章