Java ———KMP算法(字符串匹配)
来源:互联网 发布:矢量软件 编辑:程序博客网 时间:2024/06/06 10:47
问题:假设有这么一类问题:存在2个字符串,其中一个是另外一个的子串。
例如:
输入s1=abcd,s2=bc,输出:1。abcd从0开始算起。
解决一:
暴力遍历解决(遍历!!!)
思路:假设S=[a,b,c,d],p=[bc],找出P在S中的位置
1.判断s[0]==p[0],显然a!=b.
2.根据i=i-j+1,j=0; 判断s[0]==p[1],b==b成立
3.i++,j++; 判断s[1]==p[2],c=c成立,此时 符合j==p.length长度
4.return回去,已找到P字符串在S中的位置
贴代码
public static int baoli(String s[],String p[]){ int i=0,j=0; while(i<s.length&&j<p.length){ if(s[i]==p[j]){ i++; j++; } else { i=i-j+1; j=0; } } if(j==p.length) { return i - j;} else return -1; }
解法二
KMP算法
定义:Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置。
此算法可以在O(m+n)的时间数量级上完成串的模式匹配操作。其改进在于:每当一趟匹配过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽肯能远的一段距离后,继续进行比较。
例:
假设两个字符串 abcac , ababc abcac bab
第一趟匹配
i=3
a b a b c a b c a c b a b
a b c
j=3
第二躺匹配
i=3->i=7
a b a b c a b c a c b a b
a b c a c
j=1->j=5, 到第5个字符不匹配
第三趟匹配
i=7->i=11
a b a b c a b c a c b a b
(a)b c a c
j=1->j=6,5个字符匹配完成
通过对上述观察,我们可以看到i=4和j=1,i=5和j=1以及i=6,j=1这三次比较都是不必进行的,因为从第三趟结果就可以知道主串中4,5,6必然是bca,(即模式中的2,3,4)。因为模式中的第一个字符为a,因此它无需再和这三个字符进行比较,而仅需将主串中的i=4移到i=7,用i=7与j=2进行比较即可。
同理,在第一趟匹配出现字符不等时,继续将i向又移动两个字符的位置继续进行i=3,j=1的字符比较。
结论:失配时
模式串(针对整个模式串)向右移动的位数=已匹配字符数 - 失配字符的上一位字符所对应的最大长度值
得知最大长度表变可求next数组
所以我们要知道最大长度表怎么算。(以下例子很形象)
next 数组相当于“最大长度值” 整体向右移动一位,然后初始值赋为-1。就是找最大对称长度的前缀后缀,然后整体右移一位,初值赋为-1
然后便可用next数组来改变刚刚的公式
则失配时,
模式串向右移动的位数为=失配字符所在位置 - 失配字符对应的next 值
看了大致介绍,先贴代码根据代码讲解
public class KMPSearch { public static int kmpsearch(String s,String key,int[] next){ int i=0; int j=0; while (i<s.length()&&j<key.length()){ //如果j=-1或者当前字符串匹配陈功(即s[i]==key[j]),都令i++.j++ if(j==-1||s.charAt(i)==key.charAt(j)){ i++; j++; } else { //如果当前j!=-1,且当前字符匹配失败(即s[i]!=key[j]),则令i不变,j=next[j] //next[j]即为j对应的next值 j=next[j]; } } if(j==key.length()){ return i-j; } else return 0; } public static int[] kmpnext(String key){ int next[]= new int[key.length()]; next[0]=-1; int k=-1; int j=0; while (j<key.length()-1){ if(k==-1){ next[++j]=0; k=0; } else if(key.charAt(j) == key.charAt(k)){//确定next(j+1)的值 k++; next[++j]=k; } else k=next[k]; } return next; } public static void main(String args[]){ String str1="sdffsefdbababa"; String key="ababa"; int[] next=kmpnext(key); int res=kmpsearch(str1,key,next); System.out.println(res);}}
可从分析定义用递推的方法求next函数值
定义next[0]=-1;
设next[j]=k,则表明以下关系’p1……pk-1’=’pj-k+1……pj-1’
则求next[j+1]=?肯能有两种情况:
1.若pk=pj,则表明 ‘p1……pk’=’pj-k+1……pj’
next[j+1]=k+1=next[j]+1
2.若pk!=pj,则表明’p1……pk’!=’pj-k+1……pj’
则next[j+1]=k’+1
则next[j+1]=next[k]+1
所以得到next[j+1]=1.
所以总结来说next[0]=-1,比较k,j。
若S[k]=S[j],则next[j+1]=k+1.两者+1
若不相等则k[next]=k,对k重新赋值再比较,直到j循环结束。
参考:http://blog.csdn.net/christ1750/article/details/51259425
http://blog.csdn.net/v_july_v/article/details/7041827
http://blog.csdn.net/lzy969737017/article/details/38088865
- 字符串匹配—KMP算法
- 字符串匹配算法——KMP算法
- 字符串匹配算法——KMP算法
- 字符串匹配算法——KMP算法
- KMP 算法 —— 字符串匹配算法
- 字符串匹配算法——KMP算法
- KMP 算法总结—字符串匹配算法
- Java ———KMP算法(字符串匹配)
- 字符串匹配——KMP算法的Java实现
- 字符串模式匹配——KMP算法
- 字符串模式匹配——KMP算法
- KMP算法——字符串匹配问题
- 字符串匹配算法——KMP && BF
- 字符串匹配——KMP算法
- 字符串匹配——KMP算法
- 字符串匹配——KMP算法
- 字符串匹配——KMP算法
- KMP算法——字符串匹配
- Redis编程实践【pipeline和事务】
- EMQ服务器的使用
- NodeJS安装使用
- C语言中open与fopen的的解释和区别
- 2017ACM-ICPC南宁网络赛Frequent Subsets Problem(康托展开+bfs)
- Java ———KMP算法(字符串匹配)
- Java 将枚举存入List集合
- Day4 基于DrawerLayout的菜单栏设计
- Springboot学习笔记(一)FastJson解析JSON数据
- java jxl 读取excel
- 排序算法学习体会
- 磁盘阵列RAID0,1,10,5,6
- Coursera/py4inf/python data structure 笔记 密歇根大学
- Java文件压缩