kmp算法
来源:互联网 发布:e4a网络验证授权系统 编辑:程序博客网 时间:2024/06/04 20:11
kmp算法思想 找到最长的滑动区间
在KMP算法的使用中,首要任务就是获取一个字符串的next数组
next数组可以用来求重复前缀,而且求出来的重复前缀是最小的
i 1 2 3 4 5 6 7 8 从第五个开始出现了不匹配
Aa b c ab c a c 按照朴素算法 每次比到B的最后一位发现不同又要重新从B的开头和A的下一个字符比较
Ba b c ac 朴素算法不可避免的存在“回溯”现象 效率低
j 1 2 3 4 5 绿色部分在两个字符串中都是已知的 并且如果出现下图中的橙色部分
有一段字符相同 就不用一一比较了 直接滑动跳过不匹配的就好
i 1 2 3 4 5 6 7 8 即B向右滑k个长度 使得后缀(A橙色部分)=前缀(B橙色部分)
A a b cab c a c 只有这样,我们才可以右移k位后从新的位置继续比较
B ab c a c
j 1 2 3 4 5
next 0 1 1 1 2
//
1.移动位数 k = 已匹配的字符数 - 对应的部分匹配值(图中k=4-1=3)
2.字符串的部分匹配值 对应 完全匹配的字符串的最后一个字符的next值(上面 匹配了字符串abca 第二个a的next是1 则这个字符串的部分匹配值是2 而不是第二个a的部分匹配值)
3.部分匹配值是 完全前后缀中 最长的 共有元素 的长度
怎么确定滑动区间?
建立一个数组 next,它跟B串一样长,next[j]表示B[j]与A[i]不匹配时 B应该滑到哪个位置
一旦不匹配时 查一下next的值 让A[i]与B[next[j]]继续比较
求next 数组 code:
<span style="font-family:SimSun;">void getnext(int len){int i=0,j=-1;next[i]=j;//起初next[0]=-1 一般任何串的第一个字符的模式值规定为-1。 while(i<len){if(j==-1||str[i]==str[j]){i++,j++;next[i]=j;}else j=next[j];}}/*例: A a b c a b c a cB a b c a c 位序i 0 1 2 3 4 模式串 a b c a cnxet(j) -1 0 0 0 1位序以0开始时 令next=-1 (位序以1开始时 令next=0) 第一次执行while 循环 j==-1 i++,j++后 i=1,j=0 next[1]=0,即b 的next 值为0;i=1 <len str[i]==b,str[j]==str[0]==a,执行else 语句 j=next[j]=-1j==-1 执行if 语句 i=2,j=0; next[2]=0 依次执行直到i==len==5 终止循环 */ </span>
字符串匹配
匹配的代码和求next数组的代码非常相似,匹配的过程和求next数组的过程其实是一样的。假设现在字符串B的前i个位置都和从某个位置开始的字符串A匹配,现在比较第i+1个位置。如果第i+1个位置相同,接着比较第i+2个位置;如果第i+1个位置不同,则出现不匹配,我们依旧要将长度为i的字符串分割,获得其最大公共长度next[i],然后从next[i]继续比较两个字符串。这个过程和求next数组一致,所以可以匹配代码如下
<span style="font-family:SimSun;">void kmp(){get_next();//调用next 数组 获得滑动区间 int i=0,j=0;while(i<strlen(buf))//buf 主串 str 标准串{if(j==-1||buf[i]==str[j]) i++,j++;else j=next[j];}}/*i 0 1 2 3 4 5 6 7buf a b c a b c a cstr a b c a c next -1 0 0 0 1j 0 1 2 3 4while循环 第一次 i=j=0,buf[0]=str[0]=a,i++,j++,i=1,j=1第二次 同上......第五次 i=4 j=4,buf[4]= b str[4]=c 两者不等 故j=next[4]= 1i 0 1 2 3 4 5 6 7buf a b c a b c a cstr a b c a c next -1 0 0 0 1j 0 1 2 3 4 5 6 7把str 右移 使上一次未匹配成功的buf[4]与str[next[4]]相比较 */</span>
详细了解next数据值的求解方法
位序 1 2 3 4 5 6 7 8
模式串 a b a a b c a c
next值 0 1 1 2 2 3 1 2
next数组的求解方法是:
1.第一位的next值为0
2.第二位的next值为1
后面求解每一位的next值时,根据前一位进行比较
3.第三位的next值:第二位的模式串为b ,对应的next值为1;将第二位的模式串b与第一位的模式串a进行比较,不相等;则第三位的next值为1
4.第四位的next值:第三位的模式串为a ,对应的next值为1;将第三位的模式串a与第一位的模式串a进行比较,相同,则第四位的next值得为2
5.第五位的next值:第四位的模式串为a,对应的next值为2;将第四位的模式串a与第二位的模式串b进行比较,不相等;第二位的b对应的next值为1,则将第四位的模式串a与第一位的模式串a进行比较,相同,则第五位的next的值为2
6.第六位的next值:第五位的模式串为b,对应的next值为2;将第五位的模式串b与第二位的模式中b进行比较,相同,则第六位的next值为3
7.第七位的next值:第六位的模式串为c,对应的next值为3;将第六位的模式串c与第三位的模式串a进行比较,不相等;第三位的a对应的next值为1,则将第六位的模式串c与第一位的模式串a进行比较,不相同,则第七位的next值为1
8.第八位的next值:第七位的模式串为a,对应的next值为1;将第七位的模式串a与第一位的模式串a进行比较,相同,则第八位的next值为2
以上这种分析方法,位序是从1开始的,如果位序从0开始,刚第一位的next值为-1,后面的方法则相同
0 0
- KMP算法详解 【KMP】
- 【KMP】KMP算法模板
- KMP hihoCoder1015 KMP算法
- kmp算法
- KMP算法
- KMP算法
- KMP算法
- KMP算法
- KMP 算法
- kmp算法
- KMP算法
- kmp算法
- KMP算法
- KMP算法
- kmp算法
- kmp算法
- KMP算法
- KMP算法
- Asp.NET MVC X.PageList.MVC 分页详解以及自定义样式
- ubuntu挂载到开发板某个目录
- Android AlarmManager实现不间断轮询服务
- canvas绘制矩形
- LeakCanary:简单粗暴的内存泄漏检测工具
- kmp算法
- 字符指针和字符数组的初始化
- scanf
- 多校第六场 1006 hdu 5358 First One(枚举)
- Android 属性动画(Property Animation) 完全解析 (下)
- Android新技术学习——阿里巴巴免Root无侵入AOP框架Dexposed
- matlab的fopen
- android性能测试工具
- Scroll 最基本例子