您的位置:首页 > 编程语言 > Java开发

KMP算法的Java实现(优化和非优化求next数组)

2018-03-17 15:11 281 查看
最近学习在字符串匹配时,会用到KMP算法,比BF(暴力)算法性能提高了许多,于是用Java实现了一下。
算法中主要问题就是求得next数组,在这里也出现了可以优化的地方,算法原理讲解很多博客也给出,代码供上。。。
写的不好,请指出问题。

package algorithm;

public class KMR {

/**
* 记m=match.length()
* 此算法为未改进的KMP算法中的求next数组
* next[j]表示array[0]~array[j-1]中真前缀和真后缀相等的最大长度,记为k
* 在求next[j]时,对array[0]~array[j-1]进行了j-1躺搜索
* 算法复杂度为O(m^3)
* */
public static int[] getNext(String match) {

int[] next=new int[match.length()];
next[0]=-1;
int i,j,len;
for(j=1;j<match.length();j++) // 相等子串的从match[0]-match[j-1]查找
{
for( len=j-1;len>=1;len--)
{
for( i=0;i<len;i++) // 依次比较match[0]-match[len-1] 与 match[j-len]-match[j-1]
{
if(match.charAt(i)!=match.charAt(i+j-len))
break;
}
if(len==i)
{
next[j]=len;
break;
}
}
if(len<1)
next[j]=0;
}
System.out.print(match+"的next[]数组为:");
for(int interger:next)
System.out.print(interger+" ");

return next;
}

/*
* 此算法为改进过的KMP算法中的求next数组
* next[j]表示array[0]~array[j-1]中真前缀和真后缀相等的最大长度,记为k
* 我们会发现
* if(array[j]==array[k]),那么next[j]自然等于k+1,相当于原来的前缀和后缀都添加上了相同的一个字符
* if(array[j]==array[k]), 那么我们需要去求array[0]~array[j-1]中真前缀和真后缀相等的第二长的长度
* 记为k'=next[k] 再判断if(array[j]==array[k'])
* 一直做同样的操作,直到array[j]==array[k'''']或*next[k''''']=-1停止
* 算法复杂度为O(m)*/
public static int[] advancedGetNext(String match)
{

int[] next=new int[match.length()];
next[0]=-1; // 初值,每个字符串的第一个字符一定不存在最大前缀和最大后缀
int j=1;
int k=-1;
while(j<match.length())
{

if(k==-1)
{
next[j]=0;
j++;
k=next[j-1]; // 提前算好下一次迭代时的k
}
else if(match.charAt(j-1)==match.charAt(k)) {
next[j]=k+1;
j++;
k=next[j-1];
}
else {
k=next[k];
}
}
System.out.print(match+"的next[]数组为:");
for(int interger:next)
System.out.print(interger+" ");
return next;

}

public static int KMP(String str,String match) {
int[] next=advancedGetNext(match);
// int[] next=getNext(match);
int i=0,j=0;
while(i<str.length()&&j<match.length())
{
if(str.charAt(i)==match.charAt(j))
{
i++;
j++;
}
else {
j=next[j];
if(j==-1) // 子串的最大前缀和最大后缀不存在
{
i++;
j++; // 这条语句也可以写成j=0;
}
}
}
if(j==match.length())
{
return i-match.length();
}
else {
return -1;
}

}

public static void main(String[] args) {
String str="ababaababcb";
String match1="ababc";
String match2="abcd";
int index1=KMP(str,match1);
System.out.println("\n"+match1+"在"+str+"中的起始索引号为:"+index1);
int index2=KMP(str,match2);
System.out.println("\n"+match2+"在"+str+"中的起始索引号为:"+index2);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: