KMP算法

 1 /* next數組是KMP算法的關鍵,next數組的做用是:當模式串T和主串S失配  2  * ,next數組對應的元素指導應該用T串中的哪個元素進行下一輪的匹配  3  * next數組和T串相關,和S串無關。KMP的關鍵是next數組的求法。  4  *  5  * ———————————————————————————————————————————————————————————————————  6  * | T | 9 | a | b | a | b | a | a | a | b | a |  7  * ————————————————————————————————————————————————————————————————————  8  * |index| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |  9  * ————————————————————————————————————————————————————————————————————  10  * |next | X | 0 | 1 | 1 | 2 | 3 | 4 | 2 | 2 | 3 | * ————————————————————————————————————————————————————————————————————  11  *  12 step 0:  13  * j = 0; i = 1; next[1] = 0  14  * | 1 2 3 4 5 6 7 8 9 10  15  * —————————————————————————————————————————————————————————————————————  16  * i = | 1  17  * j = | 0  18  *  19 step 1:  20  * j == 0;-->i = 2;j = 1;next[2] = 1;  21  * | 1 2 3 4 5 6 7 8 9 10  22  * —————————————————————————————————————————————————————————————————————  23  * i = | 1 2  24  * j = | 0 1  25  *  26 step 2:  27  * T[2] != T[1];--> j = next[1]-->j = 0;i = 2  28  * | 1 2 3 4 5 6 7 8 9 10  29  * —————————————————————————————————————————————————————————————————————  30  * i = | 1 2 2  31  * j = | 0 1 0  32  *  33 step 3:  34  * j == 0 --> j++;i++;--> j = 1;i = 3;next[3] = 1  35  * | 1 2 3 4 5 6 7 8 9 10  36  * —————————————————————————————————————————————————————————————————————  37  * i = | 1 2 2 3  38  * j = | 0 1 0 1  39  *  40 step 4:  41  * T[3] == T[1];-->i++;j++;-->i=4,j=2; next[4] = 2  42  * | 1 2 3 4 5 6 7 8 9 10  43  * —————————————————————————————————————————————————————————————————————  44  * i = | 1 2 2 3 4  45  * j = | 0 1 0 1 2  46  *  47 step 5:  48  * T[4] == T[2];-->i++;j++-->i=5,j=3-->next[5]=3  49  * | 1 2 3 4 5 6 7 8 9 10  50  * —————————————————————————————————————————————————————————————————————  51  * i = | 1 2 2 3 4 5  52  * j = | 0 1 0 1 2 3  53  *  54 step 6:  55  * T[5] == T[3];-->i++,j++;-->i=6,j=4;next[6]=4;  56  * | 1 2 3 4 5 6 7 8 9 10  57  * —————————————————————————————————————————————————————————————————————  58  * i = | 1 2 2 3 4 5 6  59  * j = | 0 1 0 1 2 3 4  60  *  61 step 7:  62  * T[6] != T[4];-->j = next[j];-->j=2;  63  * | 1 2 3 4 5 6 7 8 9 10  64  * —————————————————————————————————————————————————————————————————————  65  * i = | 1 2 2 3 4 5 6 6  66  * j = | 0 1 0 1 2 3 4 2  67  *  68 step 8:  69  * T[2] != T[6];-->j = next[j];-->j = 1;  70  * | 1 2 3 4 5 6 7 8 9 10  71  * —————————————————————————————————————————————————————————————————————  72  * i = | 1 2 2 3 4 5 6 6 6  73  * j = | 0 1 0 1 2 3 4 2 1  74  *  75 step 9:  76  * T[1] == T[6];-->i++,j++;-->i=7,j=2;next[7]=2;  77  * | 1 2 3 4 5 6 7 8 9 10  78  * —————————————————————————————————————————————————————————————————————  79  * i = | 1 2 2 3 4 5 6 6 6 7  80  * j = | 0 1 0 1 2 3 4 2 1 2  81  *  82 step 10:  83  * T[2]!=[7];-->j=next[j];-->j=1;  84  * | 1 2 3 4 5 6 7 8 9 10 11  85  * ———————————————————————————————————————————————————————————————————————————————————  86  * i = | 1 2 2 3 4 5 6 6 6 7 7  87  * j = | 0 1 0 1 2 3 4 2 1 2 1  88  *  89 step 11:  90  * T[1]==T[7];-->i++,j++;-->i=8,j=2;-->next[8]=2;  91  * | 1 2 3 4 5 6 7 8 9 10 11 12  92  * ———————————————————————————————————————————————————————————————————————————————————  93  * i = | 1 2 2 3 4 5 6 6 6 7 7 8  94  * j = | 0 1 0 1 2 3 4 2 1 2 1 2  95  *  96 step 12:  97  * T[2]==T[8];-->i++,j++;-->i=9,j=3;next[9]=3;  98  * | 1 2 3 4 5 6 7 8 9 10 11 12  99  * ——————————————————————————————————————————————————————————————————————————————————— 100  * i = | 1 2 2 3 4 5 6 6 6 7 7 8 101  * j = | 0 1 0 1 2 3 4 2 1 2 1 2 102  * */
103 
104 
105 /* 模式串:ababaadacc 106  * 前綴和後綴的概念: 107  * 前綴:除去最後一個元素以外的全部包含第一個元素的連續字符串 108  * 對於模式串中的d則前綴有:a ab aba abab ababa 109  * 後綴:除去第一個元素以外的全部的包含最後一個元素的連續字符串 110  * 對於模式串中的d則前綴有:a aa baa abaa babaa 111  * */
112 
113 #include<stdio.h>
114 
115  //next數組的做用: 當模式串匹配失敗的時候,next數組的相對應的元素指示 116  // 要從模式串的哪一個位置開始和當前的主串的失配的元素開 117  // 始進行下一輪的匹配。
118  
119 
120 void getNext(char* T, int* next){ 121     int i = 1;              //i的值是將要計算的next的下標
122     int j = 0;                //前綴
123     next[1] = 0; 124     while( i <= 9 ){ 125         if( 0 == j || T[i] == T[j] ){ 126                     //T[i] == T[j]則向後匹配 127                     //當前的next[i]的值已經肯定爲j 128                     //j==0或爲初始,或者是沒有匹配的前綴 129                     //此時i和j自加
130             i++; 131             j++; 132             next[i] = j; 133  } 134         else{ 135             j = next[j];      //next的做用:當T[j]和T[i]失配,next[j]的值 136                     //指示的下一次要進行匹配的位置,有點像遞歸。
137  } 138  } 139 } 140 int KMP(char* S, char* T, int startPosition){ 141     int i = startPosition; 142     int j = 1; 143     int next[30]; 144  getNext(T,next); 145     while( i <= 17 && j <= 9 ){        //j>則說明匹配成功了,i>則說明失敗了
146         if( j == 0 || S[i] == T[j] ){   //j==0;能夠理解爲要從新開始
147             i++; 148             j++; 149  } 150         else{ 151             j = next[j]; 152  } 153  } 154     if( j > 9 ){ 155         return i - 9; 156  } 157     else
158         return 0; 159 } 160 
161 
162 int main(){ 163     char S[20] = " absfeafdababaaaba"; 164     char T[20] = " ababaaaba"; 165     int result; 166     result = KMP(S,T,1); 167     printf("the position is %d\n",result); 168     return 0; 169 }
相關文章
相關標籤/搜索