KMP字符串模式匹配算法(C++實現)


鑒於原理有點復雜,詳細原理可以參考這篇文章http://blog.csdn.net/v_july_v/article/details/7041827

  本文直接從結論入手,應付考試和競賽足夠了。

  設T為目標串("aaabbbaabbabcabcabbaba"),pat為模式串("aabbabc")。

  這是模式串的next數組:

j(下標) 0 1 2 3 4 5 6
pat a a b b a b c
next[j] -1 0 1 0 0 1 0

  KMP算法:

  j=0時,next[j]=-1。表示下一趟匹配比較時,模式串的第-1個字符與目標串上次失配的位置對齊。(其實等同於第0個字符與目標串上次失配的下一個位置對齊),模式串需要移動到posT-next[j]的位置。(posT為T串下標)

  j=1時,next[j]=0。表示下一趟匹配比較時,模式串的第0個字符與目標串上次失配的位置對齊。模式串需要移動到posT-next[j]個位置。

  j=2時,next[j]=1。表示下一趟匹配比較時,模式串的第1個字符與目標串上次失配的位置對齊。模式串需要移動到posT-next[j]個位置。

  以此類推......

  

  那么下面只要求出next數組即可,next數組是如何形成的?

  從下標0開始,一直到lengthP-1為止(lengthP是模式串的長度),每次尋找該下標前面前綴與后綴相同的最大長度(前后綴不包括前面整個字符串,即起始位置和終止位置都相等的那一個字符串,下面有解釋)。

  j=0時,字符a前面無字符,故標記-1;

  j=1時,字符a前面有字符a,但由於“前后綴不包括前面整個字符串”的規則,所以並沒有相同的前后綴一說,故標記為0。

  j=2時,字符b前面有字符aa,前后綴相同的字符串為a,故標記為前后綴的長度1。

  以此類推......(PS:前后綴的計算都是從左到右的)

  其實這樣說是為了方便理解next數組,而next數組的實際形成也是一次KMP算法,它也是一個匹配字符串的過程,用后綴去匹配前綴的過程。

  代碼如下:

  

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 string T;
 5 string pat;
 6 void getNext(int next[],int lengthP){//lengthP為模式串P的長度 
 7     int j=0,k=-1;//j為P串的下標,k用來記錄該下標對應的next數組的值 
 8     next[0]=-1;//初始化0下標下的next數組值為-1 
 9     while(j<lengthP){ //對模式串進行掃描 
10         if(k==-1||pat[j]==pat[k]){//串后綴與前綴沒有相等的子串或者此時j下標下的字符與k下的字符相等。 
11             j++;k++; 
12             next[j]=k;//設置next數組j下標的值為k 
13         }else
14             k=next[k];//縮小子串的范圍繼續比較 
15     }
16 }
17 
18 int kmp(int k,int next[]){
19     int posP=0,posT=k;//posP和posT分別是模式串pat和目標串T的下標,先初始化它們的起始位置 
20     int lengthP=pat.length();//lengthP是模式串pat長 
21     int lengthT=T.length();//lengthT是目標串T長 
22     while(posP<lengthP&&posT<lengthT){//對兩串掃描 
23         if(posP==-1||pat[posP]==T[posT]){//對應字符匹配 
24             posP++;posT++;
25         }else
26             posP=next[posP];//失配時,用next數組值選擇下一次匹配的位置 
27     }
28     if(posP<lengthP) return -1;
29     else return posT-lengthP;//匹配成功 
30 }
31 
32 int main(){
33     T="aaabbbaabbabcabcabbaba";
34     pat="aabbabc";
35     int lengthP=pat.length();
36     int next[lengthP]={0};
37     getNext(next,lengthP);
38     int pos=kmp(0,next);
39     cout<<pos<<endl;
40     cout<<"next[]:";
41     for(int i=0;i<lengthP;i++){
42         cout<<next[i]<<" "; 
43     } 
44     return 0;
45 }

  

  

  

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM