KMP算法初探
[edit by xingoo]
kmp算法其实就是一种改进的字符串匹配算法。复杂度可以达到O(n+m),n是参考字符串长度,m是匹配字符串长度。
传统的算法,就是匹配字符串与参考字符串挨个比较,如果相同就比较下一个,如果不相同,就返回上一次的结果,再重新比较。
如图1 如果失败则字符串会重新用S(参考字符串)的第二个,与T(匹配字符串)的第一个比较,知道全部符合查找,或找不到为止。
此时发现S[5] != T[5],因此用S[1]与T[0]进行比较。
此时发现S[1]!=T[0],因此用S[2]与T[0]比较。
此时,仍然不相等,继续后移。
此时,S[3] == T[0],继续比较,发现所有T元素都在S中找到,满足查找,返回开始匹配的下标3.
传统代码
1 int old_index(char * S,char * T){
2 int i=0;
3 int j=0;
4 while(i<strlen(S) && j<strlen(T)){
5 if( S[i] == T[j] ){
6 ++i;
7 ++j;
8 }
9 else{
10 i = i-j+1; //上一次的下一个
11 j=0;
12 }
13 }
14 if(j == strlen(T))
15 return i-strlen(T);
16 else
17 return -1;
18 }
这种比较忽略了一个问题,就是在T中,abcabx,第一个字符串因为不跟第二个,第三个一样,因此,在一开始的匹配中,可以直接跳过比较,直接从S的第三个元素开始比较。这里就涉及到一个概念:最短子串对称匹配。
首先,初始化,当j=0时,next(j)=-1;
当j=1时,字符串0到j-1,只有"a",因此 next(j) = 0;
当j=2时,字符串0到j-1,字符串为"ab",因此next(j) = 0;
当j=3时,字符串0到j-1,字符串为"abc",因此next(j) = 0;
当j=4时,字符串0到j-1,字符串为"abca",此时,前缀a在末尾出现,因此next(j) = 1;
当j=5时,字符串0到j-1,字符串为"abcab",此时,前缀ab在末尾出现,因此next(j) = 2;
最后得到next的数组为"-1 0 0 0 1 2"。
按照这个方法:
ababab的next数组为"-1 0 0 1 2 3 4"
这里面,当j=5时,字符串"ababa",前缀是"aba",后缀也是"aba",因此next值为3.
计算next数组详细代码
void getNext(char * T,int *next){
int i,j;
i=0;
j=-1;
next[0]=-1;
while(i<strlen(T)){
if(j == -1 || T[i] == T[j]){
++i;
++j;
next[i] = j;
}
else{
j = next[j];
}
}
}
kmp匹配代码
int kmp(char* S,char * T){
int i=0;
int j=0;
int next[MAX];
getNext(T,next);
while(i<strlen(S) && j<strlen(T)){
printf("i %d-%c j %d-%cn",i,S[i],j,T[j]);
if(j==0 || S[i]==T[j]){
++i;
++j;
}else{
j = next[j];
printf("j back to %dn",j);
}
}
if(j == strlen(T))
return i-strlen(T);
else
return 0;
}
全部代码
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #define MAX 20
5
6 void getNext(char * T,int *next);
7 int kmp(char * S,char * T);
8 int old_index(char * S,char * T);
9
10 int main()
11 {
12 char * s = "acabbabababc";
13 char * t = "ababab";
14
15 //printf("the pos is:%dnn",old_index(s,t));
16 //printf("the pos is:%dnn",old_index(m,t));
17 //printf("the pos is:%dnn",old_index(n,t));
18 printf("the pos is:%dn",kmp(s,t));
19 return 0;
20 }
21
22 void getNext(char * T,int *next){
23 int i,j;
24 i=0;
25 j=-1;
26 next[0]=-1;
27 while(i<strlen(T)){
28 if(j == -1 || T[i] == T[j]){
29 ++i;
30 ++j;
31 next[i] = j;
32 }
33 else{
34 j = next[j];
35 }
36 }
37 }
38
39 int kmp(char* S,char * T){
40 int i=0;
41 int j=0;
42 int next[MAX];
43 getNext(T,next);
44 while(i<strlen(S) && j<strlen(T)){
45 printf("i %d-%c j %d-%cn",i,S[i],j,T[j]);
46 if(j==0 || S[i]==T[j]){
47 ++i;
48 ++j;
49 }else{
50 j = next[j];
51 printf("j back to %dn",j);
52 }
53 }
54 if(j == strlen(T))
55 return i-strlen(T);
56 else
57 return 0;
58 }
59 int old_index(char * S,char * T){
60 int i=0;
61 int j=0;
62 while(i<strlen(S) && j<strlen(T)){
63 if( S[i] == T[j] ){
64 ++i;
65 ++j;
66 }
67 else{
68 i = i-j+1; //上一次的下一个
69 j=0;
70 }
71 }
72 if(j == strlen(T))
73 return i-strlen(T);
74 else
75 return -1;
76 }
运行结果
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 萌新不看会后悔的C++基本类型总结(一)
- 2019 ICPC 银川网络赛 D. Take Your Seat (疯子坐飞机问题)
- 2019 ICPC 银川网络赛 H. Fight Against Monsters
- 状态压缩DP(大佬写的很好,转来看)
- 2019 ICPC 银川网络赛 F-Moving On (卡Cache)
- 树形结构--二叉树的遍历算法应用(十九)
- POJ1088 滑雪题解+HDU 1078(记忆化搜索DP)
- 2019 ICPC 南京网络赛 F Greedy Sequence
- 补题Codeforces 1102E. Monotonic Renumeration
- 2019 ICPC 南京网络赛 H-Holy Grail
- 写代码?程序猿?你不能不懂的八大排序算法的Python实现
- Java开发编程规范:5.集合处理
- codeforce 272E Dima and Horses (假DFS)
- 网速慢?NO可能是路由器的原因?
- codeforce 272B Dima and Sequence