KMP算法java实现

来源:互联网 发布:linux弱口令扫描工具 编辑:程序博客网 时间:2024/06/05 07:46

一、KMP算法

在数据结构,字符串的操作中,有一个非常重要的方法,即在一个字符串中(主串)搜索一个特定的字符串(子串或模式串),若找到则返回字符串的位置,未找到则返回-1;

       最简单的方法则是采用回溯的方法,又叫Brute-Force算法,即从头遍历主串,若与子串第一个字符一样则比对第二个字符串,若不相同则回溯到第一个字符的下一个字符开始重新比较。设主串为

fffff….ffff 模式串为fffff…fffe 。则这种算法的时间复杂都为O(n*m)。

  n个f           m个字符

       编写的JAVA程序如下:

public static int BFIndex(String s,String t){int i=0,j=0;while(i<s.length()&&j<t.length()){if (s.charAt(i)==t.charAt(j)) {i++;j++;}else{i=i-j+1;j=0;}}if(j==t.length()){return i-j;}return -1;}

测试一下,Main函数:

public static void main(String[] args) {String s="aaabaaabaaabaaaab";String t="aaaab";System.out.println(BFIndex(s, t1));}

输出12。

       这种方法原理是回溯,时间复杂度过高,所以Knuth、Morris、和Pratt设计了一种算法,叫KMP算法,将时间复杂度下降至O(n+m);

       KMP算法的核心在于,模式串中是否有字符串满足

       ‘p1p2p3…pk-1’=’si-k+1si-k+2…si-1

       若含有则下一次匹配为Si与Pk若不含有,则可直接进行Si和P1的比较。

       K的取值只与模式串有关,将每一位的k值计算出来,放入数组中,称之为next数组,通过算法计算这个数组。实际就是求模式串中’p1…pk-1’=’pj-k+1…pj-1

       数组第一位的next值设为0,next[j+1]的值分两种情况,(1)若pk=pj则next[j+1]=next[j]+1=k+1 (2)若pk ≠pj则j=next[j-1]。

还需讨论如s="aaabaaabaaabaaaab" t="aaaab" 这种情况,aaaab对应的next值为01234,但是因为前面四个a都是重复的,所以实际应该为00004,根据这种情况最终编写代码如下:

public static int[] Get_next(String t){int[] next;int i=1,j=0;next=new int[t.length()];next[0]=0;while(i<t.length()){if(j==0||t.charAt(i-1)==t.charAt(j-1)){if(t.charAt(i)!=t.charAt(j)){next[i++]=++j;}else{next[i++]=next[j++];}}else {j=next[j-1];}}return next;}

算法程序如下:

private static int KMPIndex(String s, String t, int[] next) {int i=0,j=0;while(i<s.length()&&j<t.length()){if(s.charAt(i)==t.charAt(j)){i++;j++;}else{j=next[j];if(j==0){i++;}}}if(j<=t.length()){return i-j;}return -1;}


测试程序:

public static void main(String[] args) {String s="aaabaaabaaabaaaab";String t="aaaab";int [] a=Get_next(t);System.out.println(KMPIndex(s,t,a));}


得结果12;

    下面分别计算下两个方法所需时间

public static void main(String[] args) {String s="aaabaaabaaabaaaab";String t="aaaab";Long i=System.nanoTime();BFIndex(s, t);Long j=System.nanoTime();System.out.println("BF算法所需时间:"+(j-i)+"ns");Long k=System.nanoTime();int [] a=Get_next(t);KMPIndex(s,t,a);Long l=System.nanoTime();System.out.println("KMP算法所需时间:"+(l-k)+"ns");}

输出

BF算法所需时间:60413ns

KMP算法所需时间:9817ns


源码:

http://download.csdn.net/detail/dongze2/9868277

第一次发文章,欢迎大家批评指正,谢谢


原创粉丝点击