kmp算法的思想及其简单应用(java版)

kmp算法是典型的字符串匹配算法。

相对于朴素字符串匹配算法来说,由于其在计算时进行了预处理,

所以在时间复杂度上比朴素字符串匹配算法要高。

其核心在于kmp算法在计算时的预处理。

预处理是干什么呢?

这里我们先给出一个算法导论上面字符串及其预处理结果。

字符串str为ababababca

预处理结果数组为:

[0, 0, 1, 2, 3, 4, 5, 6, 0, 1]

预处理结果数组与字符串的长度是一样的。

对于预处理结果数组result来说,

result[i]=max{x<i,并且str从开始到x的字串是str从开始到i的子串的后缀}

这个可能有点难懂,我们结合实例来分析下,

很明显,

result[0]=0;

看result[1],这里str从开始到i的子串为ab

str从开始到0的子串为a,a不是ab的后缀,所以result[1]=0;

然后看result[2],这里str从开始到i的子串为aba,

str从开始到0的子串为a,a是aba的后缀,str从开始到1的子串为ab,ab不是aba的后缀,

所以result[2]=1;

然后是result[3],这里str从开始到i的子串为abab,

str从开始到0的子串为a,a不是abab的后缀,str从开始到1的子串为ab,ab是abab的后缀,str从开始到2的子串为aba,aba不是abab的后缀,

所以result[3]=2,依次类推。

匹配的时候呢,

假设我们来匹配abababac与aba

就是在abababac中查找aba在何位置出现,

那么,先查找它们的第一位,第二位,第三位,发现都匹配上了,

这个时候,输出第一个结果,但是继续查找的时候与朴素字符串匹配不同。

朴素字符串这个时候从abababac的第二位,aba的第二位开始继续搜索,

但是我们有了预处理的结果,不从aba的第一位开始搜索了,

而是从aba的第二位,abababac的第四位继续搜索。

所以时间复杂度有了提高。

下面是简单的测试程序:

/** * 在target字符串中寻找source的匹配 * @param target * @param source */ public void kmp(String target, String source) { int sourceLength = source.length(); int targetLength = target.length(); int[] result = preProcess(source); int j = 0; int k = 0; for(int i=0;i<targetLength;i++){ //找到匹配的字符时才执行 while(j>0 && source.charAt(j) != target.charAt(i)){ //设置为source中合适的位置 j = result[j-1]; } //找到一个匹配的字符 if(source.charAt(j) == target.charAt(i)){ j++; } //匹配到一个,输出结果 if(j == sourceLength){ j = result[j-1]; k++; System.out.println(“find”); } } } /** * 预处理 * @param s * @return */ public int[] preProcess(final String s) { int size = s.length(); int[] result = new int[size]; result[0] = 0; int j = 0; //循环计算 for(int i=1;i<size;i++){ while(j>0 && s.charAt(j) != s.charAt(i)){ j = result[j]; } if(s.charAt(j) == s.charAt(i)){ j++; } //找到一个结果 result[i] = j; } System.out.println(java.util.Arrays.toString(result)); return result; } public static void main(String[]args) throws Exception { final String s = “abcdabcd”; KMP k = new KMP(); k.kmp(s, “abcd”); }

下面是其的一个简单应用:

poj2406链接见:

http://poj.org/problem?id=2406

计算这个字符串被重复了多少次

这里面是kmp预处理算法的应用,

对输入字符串进行预处理,

得到最后一个字符的对应数组值,简单计算后就可以得到结果,

ac程序如下:

import java.util.Scanner; public class Problem_2406 { public static void main(String []args) throws Exception { Problem_2406 p = new Problem_2406(); Scanner scanner = new Scanner(System.in); String s = “”; while(true) { s = scanner.nextLine(); if(s.equals(“.”)) { break; } System.out.println(p.kmp(s)); } } public int kmp(String input) { int len = input.length(); int[] next = new int[len + 1]; int i = 0,j = -1; next[0] = -1; while(i < len){ if( j == -1 || input.charAt(i) == input.charAt(j)){ i++; j++; next[i] = j; }else{ j = next[j]; } } if(len % (len – next[len]) == 0){ return len /(len – next[len]); } return 1; } }

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/yaoweijq/article/details/5982508
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞