KMP算法的介绍及其Java实现
来源:互联网 发布:c 源码下载 编辑:程序博客网 时间:2024/05/17 03:52
这里有一篇好文章:http://www.cnblogs.com/c-cloud/p/3224788.html
问题:给定一个字符串,寻找在一个长字符串中有没有与给定字符串匹配的子串。
解决这个问题,称之为字符串匹配算法。当前比较经典的一个算法是KMP算法。具体过程如下:
1)给定两个字符串,从第一位开始对比。当第一位不同时,向后遍历
2)当第一位相同时,继续向后遍历
当遍历到后面时,发现不匹配了。此时就需要继续向后遍历,传统的方式是向后跳一位,但是这就造成了前面成功遍历的计算量的浪费。
KMP算法就是在当前情形的时候,寻找下一跳跳转的位数。
KMP算法是:跳转位数=已匹配的字符数-对应的部分匹配值
上面的例子中,已匹配的字符数为3,已匹配的字符串ABC的部分匹配值为0,所以跳转位数就是 3 - 0 = 3 ,继续向后遍历
至于字符串的部分匹配值,先别care,下面会介绍。
3)跳转之后,按照前面说的准则来做匹配
当前匹配完成一次,继续向后面做匹配,此时已匹配字符数为 4, 而已匹配的字符串ABCD的部分匹配值为0,跳转位数为4.
不匹配,继续向下,而此时已经到了字符串尾,这样一次遍历就完成了。
下面来讲字符串的部分匹配值的计算
字符串的部分匹配值就是当前字符串的前缀字符串集 和 后缀字符串集的公共字符串的最长的长度。
举个例子 ABCDAB
前缀集:A AB ABC ABCD ABCDA
后缀集:B AB DAB CDAB BCDAB
所以最长公共字符长度为2,所以这个字符串的部分匹配值就是2
再举个例子 ABCDA
前缀集:A AB ABC ABCD
后缀集:A DA CDA BCDA
最长公共字符串长度为1,所以这个字符串的部分匹配值就是1
最后再来讲代码实现吧,这里用java实现
import java.util.Arrays;/** * KMP算法的Java实现 */public class KMP {private int[] nextArr = null;private String originStr = null;private String moduleStr = null;public KMP(String originStr, String moduleStr) {this.originStr = originStr;this.moduleStr = moduleStr;this.nextArr = caculate_nextArr(moduleStr);}/** * 计算next数组的值(部分匹配值) * */private int[] caculate_nextArr(String str) {if (str == null || str.length() == 0) {return null;}int[] theNextArr = new int[str.length()];for (int i = 0; i < str.length(); i++) {if (i == 0) {theNextArr[i] = 0;} else if (i == 1) {if (str.charAt(0) == str.charAt(1)) {theNextArr[i] = 1;} else {theNextArr[i] = 0;}} else {int theLength2 = i;boolean hasEqual = false;for (int j = theLength2 - 1; j >= 0; j--) {String prefix_str = str.substring(0, j + 1);String suffix_str = str.substring(theLength2 - j,theLength2 + 1);if (prefix_str.equals(suffix_str)) {hasEqual = true;theNextArr[i] = prefix_str.length();break;}}if (hasEqual == false) {theNextArr[i] = 0;}}}return theNextArr;}/** * 获取子字符串在父字符串中的位置 */public int getIndexOfStr() {if (moduleStr == null || moduleStr.length() <= 0) {return -1;}if (originStr == null || originStr.length() <= 0) {return -1;}if (originStr.length() < moduleStr.length()) {return -1;}int res = -1;int totalLength = originStr.length();int origin_loc = 0;int module_loc = 0;while (true) {char c_origin = originStr.charAt(origin_loc);char c_module = moduleStr.charAt(module_loc);if (c_origin == c_module) {if (module_loc == moduleStr.length() - 1) {res = origin_loc - module_loc;break;} else {origin_loc++;module_loc++;}} else {if (module_loc == 0) {origin_loc++;} else {module_loc=nextArr[module_loc-1]; }}if (origin_loc >= totalLength) {break;}}return res;}// 测试public static void main(String[] args) {KMP ktest = new KMP("BBC ABCDAB ABCDABCDABDE", "ABDE");System.out.println("部分匹配值的next数组:");System.out.println(Arrays.toString(ktest.nextArr));int theLoc = ktest.getIndexOfStr();System.out.println();System.out.println("匹配位置在:" + theLoc);}}
- KMP算法的介绍及其Java实现
- KMP算法详解及其Java实现
- KMP算法及其实现
- java实现的KMP算法
- KMP算法的JAVA实现
- Kmp算法的java实现
- KMP算法的java实现
- KMP算法的java实现
- KMP算法的Java实现
- KMP算法的Java实现
- kmp算法及其c++实现
- kmp算法的思想及其简单应用(java版)
- java实现kmp算法
- KMP算法java实现
- Java实现KMP算法
- KMP算法java实现
- KMP算法----java实现
- KMP算法java实现
- mysql 中 时间和日期函数
- Linux常用命令:traceroute命令
- MaterialDesign_兼容性控件的使用
- 求出1~1000之间所有能被7整除的数,并每五个求一次和。
- 链接、装载与库(2)—编译和链接2.2
- KMP算法的介绍及其Java实现
- Project Euler 24
- 319. Bulb Switcher
- 配置https双向认证,以及用soapui调试
- Linux常用命令:netstat命令
- 计算机从业者的技术成长学习之路
- 九章算术卷第七 盈不足
- 关于__attribute__
- Android之MVP模式