理解KMP算法
2016-07-21 23:15
399 查看
KMP算法用于字符串的匹配。
1.KMP的原理
通常我们采用的方法是暴力匹配。时间复杂度为O(N*M)
这里面可能有很多冗余操作。
假设是在text字符串里面寻找pattern字符串。
假设N为text长度,M为pattern长度。
设N = 20, M = 8
我们从text和pattern的第一位开始比较,比较了5位,然后发现第6位不同。
如果是暴力解法,就会从text的第二位开始,然后又用pattern的第一位去开始匹配。
其实我们之前已经匹配了前5位了,也就是说text的前5位就是pattern的前5位,
我们现在在用pattern的第二位去匹配pattern的第一位。
但是pattern的第二位能不能匹配pattern的第一位,其实我们完全是知道的。
我们可以提前分析pattern,将pattern自身与自身有没有匹配的所有信息都记录下来。
放在一个叫做next的数组里面,然后要用到的时候随时查询。
之后我们每次匹配失败,我们就不用只移动一位了。
加入我们匹配了7位,然后第8位失败。
如果我们知道pattern的前7位,根本自身与自身没有重叠的,我们就直接移动7位,然后用pattern的第1位去和text的第9位比较即可。
如果我们知道pattern的前7位,有倒数2位和前2位是一样的,比如abcdeab,这个时候我们可以用pattern的第3位去和text的第9位比较。
2.算法的主线
根据1的描述。主要的流程就是这样的。
其中-1表示没有匹配,0表示有1位匹配,x表示有x+1位匹配
int kmp(char* text, char* pattern){
int N = strlen(text), M = strlen(pattern);
int next* = (int*)malloc(sizeof(int) * M);
compute_next(pattern, next);
for(int i = 0, j = -1; i < N; ++i){
while(i > -1 && text[i] != pattern[j + 1]){
j = next[j];
}
if(text[i] == pattern[i + 1]){
++j;
}
if(j == M - 1){
return i - M + 1;
}
}
}
解释,其中i是text的下标。
而j表示的是匹配的数量,-1表示没有匹配,0表示有1个匹配,所以当j == M - 1使表示M个匹配,就正好成功。
next数组表示的是pattern前x位对应有多少位是重叠的。
比如现在已经匹配了j位,next[j]就表示前j位有多少是重叠的,而现在的重叠就是移位后已经匹配的位数。
3.求取next数组
1.KMP的原理
通常我们采用的方法是暴力匹配。时间复杂度为O(N*M)
这里面可能有很多冗余操作。
假设是在text字符串里面寻找pattern字符串。
假设N为text长度,M为pattern长度。
设N = 20, M = 8
我们从text和pattern的第一位开始比较,比较了5位,然后发现第6位不同。
如果是暴力解法,就会从text的第二位开始,然后又用pattern的第一位去开始匹配。
其实我们之前已经匹配了前5位了,也就是说text的前5位就是pattern的前5位,
我们现在在用pattern的第二位去匹配pattern的第一位。
但是pattern的第二位能不能匹配pattern的第一位,其实我们完全是知道的。
我们可以提前分析pattern,将pattern自身与自身有没有匹配的所有信息都记录下来。
放在一个叫做next的数组里面,然后要用到的时候随时查询。
之后我们每次匹配失败,我们就不用只移动一位了。
加入我们匹配了7位,然后第8位失败。
如果我们知道pattern的前7位,根本自身与自身没有重叠的,我们就直接移动7位,然后用pattern的第1位去和text的第9位比较即可。
如果我们知道pattern的前7位,有倒数2位和前2位是一样的,比如abcdeab,这个时候我们可以用pattern的第3位去和text的第9位比较。
2.算法的主线
根据1的描述。主要的流程就是这样的。
其中-1表示没有匹配,0表示有1位匹配,x表示有x+1位匹配
int kmp(char* text, char* pattern){
int N = strlen(text), M = strlen(pattern);
int next* = (int*)malloc(sizeof(int) * M);
compute_next(pattern, next);
for(int i = 0, j = -1; i < N; ++i){
while(i > -1 && text[i] != pattern[j + 1]){
j = next[j];
}
if(text[i] == pattern[i + 1]){
++j;
}
if(j == M - 1){
return i - M + 1;
}
}
}
解释,其中i是text的下标。
而j表示的是匹配的数量,-1表示没有匹配,0表示有1个匹配,所以当j == M - 1使表示M个匹配,就正好成功。
next数组表示的是pattern前x位对应有多少位是重叠的。
比如现在已经匹配了j位,next[j]就表示前j位有多少是重叠的,而现在的重叠就是移位后已经匹配的位数。
3.求取next数组
相关文章推荐
- CodeForces 599A Patrick and Shopping
- 3.2.4页面分配策略
- INT_MIN与溢出
- Java Filter过滤器简介
- 安装python-memached
- MySQL数据库中QueryCache的锁模型
- 随机过程学习之更新过程
- QT对access数据库进行操作
- 人生最大的痛苦,不是学不会,而是学得快忘得更快
- HDU-5726 GCD
- 核心动画之基本动画CABasicAnimation
- https交互过程
- 华为721-----内联inline,虚函数virtual
- linux下执行mysql的sql文件
- MySQL多线程同步MySQL-Transfer介绍
- 性能测试(持续更新)
- Objective-C & Sprite Kit太空历险记 : 9. 冷冻生化战士——归档
- hadoop 使用内部RPC技术实现通信
- HTML基础知识整理
- 说说React的事(二)