扩展kmp算法讲解
2016-02-22 15:53
288 查看
参考文章http://www.cnblogs.com/10jschen/archive/2012/09/03/2668149.html
一.扩展kmp得到的是什么
字符串A,B。B是模式串(子串)。求解A[i ……lenA -1]与B的最长公共前缀,记录在数组ex[i]中
二.算法实现
分为两步,第一步是对B模式串进行处理也是求B[i,Blen - 1]与B的最长公共前缀,用next数组存储,第二部是将A与B进行匹配,其实他们的方法是一样的
我们先对第二步进行分析
首先假设B的nexta[]的值已经全部求出,且i之前全部的ex值也已经求出,再设p为匹配过程中的最大位置,设k为达到最大位置时的起始位置,由此可知p = k + ex[k] - 1
由ex的定义可知:A[k……k + ex[k] -1] 与B[0……ex[k] - 1]相等 显然i > k 所以 A[i……k + ex[k] - 1]
与 B[i - k……ex[k]-1] 匹配,设L = nexta[i - k],根据nexta的定义有B[0……L-1] = B[i-k……i - k + L - 1]
只需判断ex[k] - 1(=p - k ) 与 i - k + L - 1那个大
1.i - k + L - 1 < p - k 及 p > i + L - 1,p >= i + L
由 A[i……p] 与 B[i - k……p-k] 匹配得到A[i……L + i - 1]与B[i - k……i - k + L - 1] ,又有B[0……L-1] = B[i-k……i
- k + L - 1]。故A[i……L + i - 1] =
B[0……L-1]
可知ex[i] >= L,如果ex[i] > L则A[i……L
+ i ] = B[0……L] .因为p =
k + ex[k] - 1 >= i + L,所以A[i……L + i] = B[i - k……i - k + L],推出B[0……L] =
k + ex[k] - 1与next数组定义不符合。所以ex[i] = L
2.i
- k + L - 1 >= p - k 及 p <= i + L - 1,p < i + L
A[i……p]
= B[i - k……p-k]
B[0……L-1]
= B[i-k……i - k + L - 1] 所以B[0……p -i] = B[i-k……p - k]
所以A[i……p]
= B[0……p
-i],p是匹配到的最远的地方,需要继续从A[p + 1] 和 B[p - i + 1]开始继续匹配
设j
= p
- i + 1,则
p + 1 = i + j。p增加了,所以要更新p和k的值
ps:注意j如果是小于零的就让j = 0,从B的最前端开始匹配
第一步显然和第二步的方法是一样的,注意第一步中都是nexta数组
对于B来说nexta[0]
肯定等于n,然后求出nexta[1]的最远距离,另k = 1,不用对p赋值
对于AB匹配来说,要遍历求出extend[0],遍历应该到两个字符串中长度较短的一个就停止。并另k
= 0。
代码如下
一.扩展kmp得到的是什么
字符串A,B。B是模式串(子串)。求解A[i ……lenA -1]与B的最长公共前缀,记录在数组ex[i]中
二.算法实现
分为两步,第一步是对B模式串进行处理也是求B[i,Blen - 1]与B的最长公共前缀,用next数组存储,第二部是将A与B进行匹配,其实他们的方法是一样的
我们先对第二步进行分析
首先假设B的nexta[]的值已经全部求出,且i之前全部的ex值也已经求出,再设p为匹配过程中的最大位置,设k为达到最大位置时的起始位置,由此可知p = k + ex[k] - 1
由ex的定义可知:A[k……k + ex[k] -1] 与B[0……ex[k] - 1]相等 显然i > k 所以 A[i……k + ex[k] - 1]
与 B[i - k……ex[k]-1] 匹配,设L = nexta[i - k],根据nexta的定义有B[0……L-1] = B[i-k……i - k + L - 1]
只需判断ex[k] - 1(=p - k ) 与 i - k + L - 1那个大
1.i - k + L - 1 < p - k 及 p > i + L - 1,p >= i + L
由 A[i……p] 与 B[i - k……p-k] 匹配得到A[i……L + i - 1]与B[i - k……i - k + L - 1] ,又有B[0……L-1] = B[i-k……i
- k + L - 1]。故A[i……L + i - 1] =
B[0……L-1]
可知ex[i] >= L,如果ex[i] > L则A[i……L
+ i ] = B[0……L] .因为p =
k + ex[k] - 1 >= i + L,所以A[i……L + i] = B[i - k……i - k + L],推出B[0……L] =
k + ex[k] - 1与next数组定义不符合。所以ex[i] = L
2.i
- k + L - 1 >= p - k 及 p <= i + L - 1,p < i + L
A[i……p]
= B[i - k……p-k]
B[0……L-1]
= B[i-k……i - k + L - 1] 所以B[0……p -i] = B[i-k……p - k]
所以A[i……p]
= B[0……p
-i],p是匹配到的最远的地方,需要继续从A[p + 1] 和 B[p - i + 1]开始继续匹配
设j
= p
- i + 1,则
p + 1 = i + j。p增加了,所以要更新p和k的值
ps:注意j如果是小于零的就让j = 0,从B的最前端开始匹配
第一步显然和第二步的方法是一样的,注意第一步中都是nexta数组
对于B来说nexta[0]
肯定等于n,然后求出nexta[1]的最远距离,另k = 1,不用对p赋值
对于AB匹配来说,要遍历求出extend[0],遍历应该到两个字符串中长度较短的一个就停止。并另k
= 0。
代码如下
//需定义extend 和 nexta void EKMP(char s[],char t[])//s主串,t模式串 { memset(nexta,0,sizeof(nexta)); memset(extend,0,sizeof(extend)); int slen = strlen(s),tlen = strlen(t); int len = min(slen,tlen); nexta[0] = tlen; int k; for(k = 0;k + 1 < tlen && t[k] == t[k + 1];k ++ ) { } nexta[1] = k; k = 1; int p,L,j; for(int i = 2; i < tlen; i ++) { p = k + nexta[k] - 1, L = nexta[i - k]; if(i + L <= p) { nexta[i] = L; } else { j = p - i + 1; if(j < 0) j = 0; while(i + j < tlen && t[i + j] == t[j]) { j++; } nexta[i] = j; k = i; } } for(k = 0;k < len && s[k] == t[k];k ++ ) { } extend[0] = k; k = 0; for(int i = 1; i < slen; i ++) { p = k + extend[k] - 1, L = nexta[i - k];//注意p是加extend if(i + L <= p) { extend[i] = L; } else { int j = p - i + 1; if(j < 0) j = 0; while(i + j < slen &&j < tlen && s[i + j] == t[j]) { j++; } extend[i] = j; k = i; } } }
相关文章推荐
- 数据库链接字符串查询网站
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Flex字符串比较 还有Flex字符串操作
- Ruby实现的矩阵连乘算法
- Ruby中创建字符串的一些技巧小结
- ASP下经常用的字符串等函数参考资料
- 将字符串小写转大写并延时输出的批处理代码
- 将字符串转换成System.Drawing.Color类型的方法
- C#插入法排序算法实例分析
- Lua源码中字符串类型的实现
- Lua性能优化技巧(四):关于字符串
- 字符串聚合函数(去除重复值)
- Ruby中的字符串编写示例
- 总结的5个C#字符串操作方法分享
- sqlserver中求字符串中汉字的个数的sql语句
- sql server字符串非空判断实现方法
- VBS的字符串及日期操作相关函数
- C#实现将千分位字符串转换成数字的方法
- jquery 删除字符串最后一个字符的方法解析