KMP算法

Posted robin_X

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于KMP算法的主要内容,如果未能解决你的问题,请参考以下文章

数据结构—串KMP模式匹配算法

Python ---- KMP(博文推荐+代码)

KMP算法及Python代码

KMP算法及Python代码

图解KMP算法原理及其代码分析

Kmp算法Java代码实现