Java实现 字符串匹配 KMP 算法
2014-03-10 15:56
666 查看
字符串匹配过程中,如果使用蛮力算法,效率非常的差,在此介绍一种较为高效的匹配算法KMP算法。
其主要思想是从匹配的模版去分析,即去分析Pattern串的自身规律,进而去优化匹配的效率。例如字符串“ababcb”,明显看出是ab出现一组重复,若出现如下匹配模式:
text:abababcb
pattern: ababcb
此时发生错误,一般情况下会选择移动Pattern一个位置来继续,事实证明效果不佳。聪明的人一眼就看出来,下一步应该进行这样的匹配
text:abababcb
pattern: ababcb
通过一次移动两个位置便迅速完成匹配,而移动的位置大小也恰恰是ab这个重复串的大小,所以,匹配每次移动的位置一定和当前字符串的真前缀真后缀有关,根据科学家实验,移动的位置==最大相等真前后缀的长度,此时我们需要一个和模版一样长的数组去存放Pattern下次要移动的位置,我们称Nexd[]。
对于Parrern:"a b a b c b" 这个模版来讲,
它的next[]: -1 0 0 1 2 0
其中数字next[i]代表下次模版需要用Pattern[next[i]]去匹配text,而-1代表整个模版直接跳过当前字符。所以,算法的关键其实就是算出next[].
结果:
-1 0 0 1 2 0
8
23
2
结论:一种高效的算法,在英文匹配上比较出色,也可以将其用在byte匹配上~
另一种更高效的算法BM,期待下一篇~
其主要思想是从匹配的模版去分析,即去分析Pattern串的自身规律,进而去优化匹配的效率。例如字符串“ababcb”,明显看出是ab出现一组重复,若出现如下匹配模式:
text:abababcb
pattern: ababcb
此时发生错误,一般情况下会选择移动Pattern一个位置来继续,事实证明效果不佳。聪明的人一眼就看出来,下一步应该进行这样的匹配
text:abababcb
pattern: ababcb
通过一次移动两个位置便迅速完成匹配,而移动的位置大小也恰恰是ab这个重复串的大小,所以,匹配每次移动的位置一定和当前字符串的真前缀真后缀有关,根据科学家实验,移动的位置==最大相等真前后缀的长度,此时我们需要一个和模版一样长的数组去存放Pattern下次要移动的位置,我们称Nexd[]。
对于Parrern:"a b a b c b" 这个模版来讲,
它的next[]: -1 0 0 1 2 0
其中数字next[i]代表下次模版需要用Pattern[next[i]]去匹配text,而-1代表整个模版直接跳过当前字符。所以,算法的关键其实就是算出next[].
public class KMP { public KMP() { } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String text = "ab abcb ababcb abab cb ababcb ababc "; String pattern ="ababcb"; showList(getNext(pattern)); kmpScan(text, getNext(pattern), pattern); } public static void kmpScan(String str, int[] next,String pattern) { int k =0; int j =0; int count =0; int index =0; //int[] index = new int[count]; while(k<str.length()) { if(j==-1&&k<str.length()) { k++; j=0; } else if(str.charAt(k)==pattern.charAt(j)) { j++; k++; } else{ j=next[j]; } if(j==pattern.length()) { index = k-j; j=0; k++; count++; System.out.println(index);//记录了字符出现的位置 } } System.out.println(count); } public static int[] getNext(String pattern) { char[] pat = pattern.toCharArray(); int[] next = new int[pattern.length()]; next[0]=-1; next[1]=0; for (int i = 2; i < next.length; i++) { int k=next[i-1]; while(k>=0) { if(pat[k]==pat[i-1]) break; k=next[k]; } next[i]=k+1; } return next; } public static void showList(int next[]) { for (int i = 0; i < next.length; i++) { System.out.printf("%d ",next[i]); } System.out.println(); } }
结果:
-1 0 0 1 2 0
8
23
2
结论:一种高效的算法,在英文匹配上比较出色,也可以将其用在byte匹配上~
另一种更高效的算法BM,期待下一篇~
相关文章推荐
- 字符串匹配算法之___Sunday算法的java实现
- 多模字符串匹配算法原理及Java实现代码
- 算法学习(java实现之字符串篇)·····判断字符串是否没有重复字符
- Java实现算法导论中Rabin-Karp字符串匹配算法
- 【数据结构&&等差数列】KMP简介和算法的实现(c++ && java)
- KMP、BM、Sunday等字符串匹配算法及实现
- 算法实现-->字符串匹配
- KMP字符串匹配算法及C语言实现
- 算法导论-第32章-字符串匹配:Knuth-Morris-Pratt(KMP)算法C++实现
- 【数据结构&&等差数列】KMP简介和算法的实现(c++ && java)
- 算法学习(Java实现之字符串篇)····二进制求和
- 字符串匹配算法KMP实现
- 算法 字符串匹配之朴素算法和KMP算法及JAVA代码实现
- 字符串匹配算法之KMP&Boyer-Moore
- Java 字符串匹配算法
- Java KMP匹配算法的实现
- 字符串匹配之KMP算法思路、原理与Java实现
- 【博客地址】:KMP字符串匹配算法与next数组
- BM和KMP字符串匹配算法学习
- Kmp字符串匹配算法改进版