KMP算法(克努特-莫里斯-普拉特操作)简介
来源:互联网 发布:时代超群步进软件 编辑:程序博客网 时间:2024/04/27 23:12
一,串的模式匹配算法
子串的定位操作通常称作串的模式匹配(其中T称为模式串),是各种串处理系统中最重要的操作之一。求子串位置的定位函数Index(S,T,pos)如下:
int Index(SString S,SString T,int pos){//返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0//其中T非空,1<=pos<=Strlen(S)i = pos; j = 1;while(i <= S[0] && j <= T[0]){if(S[i] == T[j]){i++;j++;}//一个字符匹配成功继续匹配后续字符else{i = i-j+2;j = 1;}//主串指针后退到出发位置的下一位重新匹配}if(j > T[0]) return i - T[0];else return 0;}
算法的基本思想是:从主串S的第pos个字符起和模式串T的第一个字符比较,若相等,则继续逐个比较后续字符;否则从主串的下一个字符起再重新和模式串比较。以此类推直到模式串的每个字符以此和主串中的一个连续的字符序列相等,则称匹配成功,函数值为和模式串T中第一个字符相等的字符在主串S中的序号,否则称匹配不成功,函数值为0。这种算法的时间复杂度为O(m*n)。
二,KMP算法的基本思路
假设主串为's[1]s[2]s[3]...s[n]',模式串为'p[1]p[2]p[3]...p[m]',当主串的第i个字符与模式串中的第j个字符不相同时,并不用将主串指针回溯,而是可以“移动”模式串,使s[i]与j[k]继续比较。那么这个k就应该满足下面的关系:
k是使得 'p[1]p[2]...p[k-1] ' = 's[i-k+1]s[i-k+2]...s[i-1]' 的最大值
记next[j] = k,如果我们已知匹配串每一位的next[j],则KMP算法的子串定位函数为:
int Index_KMP(SString S,SString T,int pos){//利用模式串T的next值求T在主串S的第pos个字符之后的位置//KMP算法i = pos;j = 1;while(i <= S[0] && j <= T[0]){if(j == 0 || S[i] == T[j]){i++;j++;}else j = next[j];}if(j > T[0]) return i - T[0];else return 0;}
三,next[j]的计算方法
当产生“失配”时,已有的部分匹配结果是:
‘p[j-k+1]p[j-k+2]...p[j-1]' = 's[i-k+1]s[i-k+2]...s[i-1]'
则有:
'p[1]p[2]...p[k-1] ' = ‘p[j-k+1]p[j-k+2]...p[j-1]'
首先,由定义知,next[1] = 0,
其次,对于任意的j >= 0,
(1)若p[j] == p[next[j]],即:'p[1]p[2]...p[k] ' = ‘p[j-k+1]p[j-k+2]...p[j]'
则有next[j+1] = next[j] + 1.
(2)若p[j] != p[next[j]],则可将问题看做用模式串匹配模式串自己的问题,那么此时应用p[j]与p[next[next[j]]]比较直到next值为0:
void get_next(SString T,int next[]){ //求模式串T的next函数值并保存在数组next中 i = 1;next[1] = 0;j = 0; while(i < T[0]){ if(j == 0 || T[i] == T[j]){i++;j++;next[i] = j;} else j = next[j]; }}//get_next
四,next[j]计算方法的修正
我们发现如果模式串中有类似“aaabaaaaaaab”的结构,那么在计算next值的时候会有很多不必要的重复计算,主要原因就是连续有几个相同的字符,那么其实这些字符的next值是一样的,没有必要反复计算,所以我们需要对计算next的方法进行一些修正:
void get_next(SString T,int next[]){ //求模式串T的next函数值并保存在数组next中 i = 1;next[1] = 0;j = 0; while(i < T[0]){ if(j == 0 || T[i] == T[j]){ i++;j++; if(T[i] != T[j]) next[i] = j; else next[i] = next[j]; } else j = next[j]; }}//get_next
- KMP算法(克努特-莫里斯-普拉特操作)简介
- 克努特-莫里斯-普拉特操作(简称KMP算法)
- 克努特-莫里斯-普拉特操作(KMP算法)
- 4.3.2 KMP克努特-莫里斯-普拉特操作
- 克努斯-莫里斯-普拉特算法(Knuth–Morris–Pratt algorithm) c简单实现
- 字符串查找-普通方法和KMP(普拉特操作)介绍
- KMP算法简介
- KMP算法简介
- KMP算法简介
- 串的操作(KMP算法实现)
- 数据结构之KMP算法简介
- 埃瓦里斯特·伽罗瓦Évariste Galois
- KMP算法简介(next数组的计算方法)
- 莫里斯蠕虫
- BF算法和KMP算法的简介
- 算法简介—KMP配图详解
- KMP算法简介及代码实现
- 并行支持向量机算法的知识点之乔里斯基分解(Cholesky factorization)
- 网线正常、网卡正常但是显示连接断开的解决
- LeetCode刷题(6)
- 听说现在赶火车刷脸就进站了!Out,跟脸有关的最新玩法是你说什么,表情包就演什么
- 1070. 结绳(25)
- 迅雷创始人程浩写了篇5万+的文章,告诫你创业AI前,必须注意的6大核心问题
- KMP算法(克努特-莫里斯-普拉特操作)简介
- 排序算法之梳排序
- 一个项目:前期准备
- Mybatis事务(一)事务管理方式(JDBC和MANAGED)
- 请将插入点移动到word域以外-NoteExpress
- java提高篇(49)--注解(Annotation)自定义注解入门
- 休闲
- 制作平滑的路径-贝塞尔曲线
- eclipse-CDT 下 openCV 环境建立