一、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
测试一下,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
算法程序如下:
private static int KMPIndex(String s, String t, int[] next) {
int i=0,j=0;
while(i
测试程序:
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
第一次发文章,欢迎大家批评指正,谢谢