字符串查找算法kmp
来源:互联网 发布:钉钉办公软件有mac版 编辑:程序博客网 时间:2024/06/04 18:24
给定一个文本串s,和一个匹配串p,要求查找p第一次在s中出现的位置。
常见的方法如暴力搜素,逐个匹配s[i],p[j],若匹配,下标后移。不匹配,i回溯到这次匹配前的下一位置,j置为0,重新匹配。最坏情况,时间复杂度O(n*m)。
int violenceSearch(char *s,char *p){ int i=0,j=0; int lenp=strlen(p); int lenS=strlen(s); while(j<lenp&&i<lens){ if(s[i]==p[j]){ i++; j++; } else{ i=i-j+1; j=0; } } if(j==len) return i-j; return ;}
每次s[i] , p[j]不匹配总要将i回溯到到下一位置,j置0,这样做可能还是会导致不匹配,又要i回溯,j置0……造成不必要的开销,kmp查找算法的做法就是令i不回溯,当不匹配的时候令j置为next[j], 再将s[i]与p[next[j]]进行匹配,这种做法的好处是不用回溯i,最坏情况时间复杂度O(n+m)。
int kmpSearch(char *s,char *p){ int i=0,j=0; int lens=strlen(s); int lenp=strlen(p); while(i<lens&&j<lenp){ if(j==-1||s[i]==p[j]){//当j==-1时,表示将匹配串的首位和文本串进行匹配,即i=i+1,j=0. i++; j++; } else j=next[j]; } if(j==lenp)return i-j; return ;}
这里维护的next[j]是在匹配串p上p[j]之前(不包含p[j])的子串的相同最长前缀后缀的长度
如给定匹配串ABCDABD,对应next[]:
kmp的精髓应该就在求解next[]数组上,即知道next[0….j],如何求解next[j+1]:
•若p[k] == p[j],则next[j + 1 ] = next [j] + 1 = k + 1;
•若p[k ] ≠ p[j],如果此时p[ next[k] ] == p[j ],则next[ j + 1 ] = next[k] + 1,否则继续递归前缀索引k = next[k],而后重复此过程。 相当于在字符p[j+1]之前不存在长度为k+1的前缀”p0 p1, …, pk-1 pk”跟后缀“pj-k pj-k+1, …, pj-1 pj”相等,那么是否可能存在另一个值t+1 < k+1,使得长度更小的前缀 “p0 p1, …, pt-1 pt” 等于长度更小的后缀 “pj-t pj-t+1, …, pj-1 pj” 呢?如果存在,那么这个t+1 便是next[ j+1]的值,此相当于利用已经求得的next 数组(next [0, …, k, …, j])进行P串前缀跟P串后缀的匹配。
void getnext(char *p,int next[]){ int k=-1; int j=0; int next[0]=-1; int len=strlen(p); while(j<len-1){ if(k=-1||p[k]==p[j]){//p[k]表示前缀,p[j]表示后缀。 //k=-1时,这时之前的串没有相等的前缀后缀,即next[j+1]=0; ++j; ++k; next[j]=k; } else k=next[k]; }}
其实next [j]数组只要将各个最大前缀后缀(这时包括next[j]这个元素)的公共元素的长度值右移一位,且把初值赋为-1 即可。
next数组的优化:
当匹配串p[j]!=s[i]的时候,这时就要用p[next[j]]与s[i]进行匹配但是如
果p[j]==p[next[j]],就一定会导致这次的匹配失败。所以不允许p[j]==p
[next[j]],如果相等,就再次递归让p[next[next[j]]]与s[i]进行匹配
(即next[j]=next[next[j]])。
void GetNextval(char *p,int next[]){ int k=-1; int j=0; int next[0]=-1; int len=strlen(p); while(j<len-1){ if(k=-1||p[k]==p[j]){ //p[k]表示前缀,p[j]表示后缀。 //k=-1时,这时之前的串没有相等的前缀后缀,即next[j+1]=0; ++j; ++k; if(p[j]!=p[k]) next[j]=k;//没改动前只有这行赋值。 else next[j]=next[k];//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] } else k=next[k]; }}
唯一参考:http://blog.csdn.net/v_july_v/article/details/7041827
精简了参考的这篇经典博文,是学习的一个记录,很多细节都没详细的阐述。
- KMP算法查找字符串
- KMP字符串查找算法
- KMP字符串查找算法
- 字符串查找算法-KMP
- KMP - 字符串查找算法
- 字符串查找算法kmp
- 字符串查找算法kmp
- KMP字符串查找算法
- KMP字符串查找算法
- 查找字符串之 KMP算法
- KMP子字符串查找算法
- 字符串的查找--KMP算法
- 字符串查找(2)KMP算法
- 字符串匹配查找算法-KMP
- KMP算法:查找子字符串
- KMP算法查找相同字符串
- WINX新增(1): KMP字符串查找算法
- WINX新增(1): KMP字符串查找算法
- solr 语法
- 排序算法总结之冒泡排序 Bubble Sort
- Pyhton:解决在IDLE中Pyhton新建列表失败的问题
- Mode bus
- Margin折叠,站在设计者的角度思考
- 字符串查找算法kmp
- @SuppressWarnings的使用、作用、用法
- 用fragment进行UI管理
- 关于android videoview视频不能匹配整个videoview控件的问题
- 左旋转字符串
- 1.4 Prototype(原型) -- 对象创建型模式
- A04在Yaliの生态(下)
- 浅谈四轴PID调试心得(转载)
- 第23讲-项目三-两段函数求值