KMP算法--纯代码

直接上代码,都在注释里了。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 //KMP
 5 //判断已经不等过的,不在重新判断
 6 //判断过已经相等的,也不再重新进行判断
 7 /*
 8     与朴素模式相比,KMP算法省去了回溯的重复问题,对判断到的相等或者不等的情况进行合理重复利用,避免多次判断的时间复杂度提升。
 9 */
10 
11 //算法代码实现
12 //这段代码的目的就是为了计算出当前要匹配的串T的next数组
13 void get_next(char * T, int *next)
14 {
15     int i, j;
16     i = 1;
17     j = 0;
18     next[1] = 0;
19     while (i < T[0])
20     {
21         if ((j == 0) || (T[i] == T[j])) //T[i]表示后缀的单个字符,T[j]表示前缀的单个字符
22         {
23             j++;
24             i++;
25             next[i] = j;
26         }
27         else
28         {
29             j = next[j]; //若字符不相同,则j值回溯
30         }
31     }
32 }
33 
34 /* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
35 /* T非空,1≤pos≤StrLength(S)。 */
36 /*
37     KMP算法的时间复杂度为O(n+m),与朴素模式的O((n-m+1)*m)相比,优化不少。
38     但是也需要强调的是,KMP算法在模式与主串之间存在许多“部分匹配”的情况下才能体现出它的优势
39     否则两者差异并不明显
40 */
41 int Index_KMP(char *S, char *T, int pos)
42 {
43     int i = pos; //i用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配
44     int j = 1; //j用于子串T中当前位置下标
45     int next[255]; //定义一组next数组
46     get_next(T, next); //对串T做分析,得到next数组
47     while (i <= S[0] && j <= T[0]) //若i小于S的长度且j小于T的长度时,循环继续
48     {
49           if (j == 0 || S[i] == T[j]) //两字母相等时则继续,与朴素算法相比,增加了j=0的判断
50           {
51               i++;
52               j++;
53           } else {
54               j = next[j]; // j回到合适的位置,i值不变
55           }
56     }
57 
58     if (j > T[0]) {
59         return i - T[0];
60     } else {
61         return 0;
62     }
63 }
64 
65 //KMP模式匹配算法改进
66 //求模式串T的next函数修正值并存入数组nextval
67 void GetNextVal(char *T, int *nextval)
68 {
69     int i, j;
70     i = 1;
71     j = 0;
72     nextval[1] = 0;
73     while (i < T[0]) {
74         if (j == 0 || T[i] == T[j]) {
75             i++;
76             j++;
77             if (T[i] != T[j]) //若当前字符与前缀字符不同
78                 nextval[i] = j; //则当前的j为nextval在i位置的值
79             else
80                 nextval[i] = nextval[j]; //如果与前缀字符相同,则将前缀字符的nextval值赋值给nextval[i]
81         } else
82             j = nextval[j]; //若字符不相同,则j值回溯
83     }
84 }
85 
86 //实际匹配算法则只需要将"get_next(T, next)"改为"GetNextVal(T, next)"即可。
87 
88 int main()
89 {
90     printf("hello world\n");
91     return 0;
92 }

 

上一篇:串的模式匹配算法


下一篇:基础数据结构及其基本应用 —— 串