kmp
来源:互联网 发布:程序员游戏 编辑:程序博客网 时间:2024/06/09 00:32
kmp是一种字符串匹配算法,假设主串为s,长度为n,模式串为p,长度为m,则简单模式匹配算法最槽糕的情况下时间复杂度为O(m*n),因为s的指针在匹配会进行回溯,而kmp算法提供了一种s指针只增不减的算法,可以保证最坏时间复杂度为O(n+m)。假设主串s的当前指针为i,模式串p当前指针为j,基本思路为
1.若s[i] == p[j],则i++,j++,与简单模式匹配相同
2.若不相等,则根据next数组对j进行回溯
3.若j增长到m,则存在匹配
kmp的核心是如何保持i不变,而对j进行回溯,即next数组的求解,依据的是前缀和后缀相等的最大长度,主要思路为
1.若k == 0,则next[k] = -1
2.假设next[k] == num ,若p[k] = p[num],则p[k+1] = num+1
3.假设next[k] == num ,若p[k] != p[num] ,则将num置为next[num]继续比较
void GetNext(char *p, int *next){int i = 0, j = -1;next[0] = -1;int m = strlen(p);while(i < m){if(j == -1 || p[i] == p[j])next[++i] = ++j;elsej = next[j];}}
...aaac...
aaaa.
p串中的'a'和S串中的'c'失配,而'a'的next值指的还是'a',那同样的比较还是会失配,而这样的比较是多余的,如果我事先知道,当 T[i]==T[j],那next[i]就设为next[j],在求next值的时候就已经比较了,这样就可以去掉这样的多余的比较。于是稍加改进得到:
void GetNext(char *p, int *next){int i = 0, j = -1;next[0] = -1;int m = strlen(p);while(i < m){if(j == -1 || p[i] == p[j]){if(p[++i] == p[++j])next[i] = next[j];elsenext[i] = j;}elsej = next[j];}}下面是两种next数组的举例(1是改进版):
下标
0
1
2
3
4
5
6
7
8
T
a
b
a
b
c
a
a
b
c
(1) next
-1
0
-1
0
2
-1
1
0
2
(2) next
-1
0
0
1
2
0
1
1
2
下标
0
1
2
3
4
T
a
b
c
a
c
(1)next
-1
0
0
-1
1
(2)next
-1
0
0
0
1
下标
0
1
2
3
4
5
6
7
T
a
d
C
a
d
C
a
d
(1)next
-1
0
0
-1
0
0
-1
0
(2)next
-1
0
0
0
1
2
3
4
kmp实现如下:int kmp(char *s, char *p){int m = strlen(p);int n = strlen(s);int *next = new int[m];GetNext(p,next);int i = 0, j = 0;while(i < n && j < m){if(j == -1 || s[i] == p[j]){++i;++j;}elsej = next[j];}delete []next;if(j == m)return i-m;else return -1;}
0 0
- KMP
- KMP
- KMP
- KMP
- KMP
- KMP
- kmp
- kmp
- KMP
- kmp
- KMP
- KMP
- KMP
- kmp
- KMP
- KMP
- kmp
- KMP
- 3Sum
- JavaScript脚本编写的两个创意时钟
- iOS绘图教程
- HDU 2586——How far away ?(LCA)
- fedora 20 KDE版本设置中文
- kmp
- 15-1-(2)-工资数据的输入(文件)
- 数据结构:树的BFS,树的层次遍历! 按先序遍历创建一棵树,然后以层次遍历输出。
- 让MFC程序隐藏运行界面
- 第十五周项目2-用文件保存的学生名单
- ScrollView同时嵌套ListView和GridView怎么解决?(参考我上一片博文!!!!)
- 一些编译错误
- 求大神把这个橡皮筋技术代码用类封装!!!!
- memcache和memcached区别