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算法的主要内容,如果未能解决你的问题,请参考以下文章