简单用图了解一下KMP算法
KMP算法是字符查找算法,假设有两个字符串,Text和Partterns,检查Text中是否存在partterns,用的KMP算法。
此算法用到 前缀和后缀的概念,具体如下:
上代码
/**
* KMP算法
* @author SuMalago
*
*/
public class KMPCalculator {
public static void main(String[] args) {
String partterns = "ABDCABDA";
String text = "ABDCADAAABDCABDADDABDCABDA";
KMPSearch(text,partterns);
}
/**
* @param textStr 长字符串
* @param partterns 短字符串
*/
public static void KMPSearch(String textStr,String partterns){
char[] parttern = partterns.toCharArray();
int pLen = parttern.length;
int[] next = getNextArray(prefixArray(parttern,pLen));
int p = 0;//用来循环parttern 方便好记取首字母p
char[] text = textStr.toCharArray();
int tLen = text.length;
int t = 0;//用来循环text 方便好记取首字母t
while(t<tLen){
//这里是最后一步,走到最后parttern检查完了,且最后的位置下的字符也相同
if(p == pLen-1 && parttern[p] == text[t]){
System.out.println(" parttern is index of :"+ (t-p));
p=next[p];
}
if(parttern[p] == text[t]){//匹配到 继续循环走下一个
p++;t++;//两个都后移
}else{
//使用next下的下标p的值(此值是前面的,肯定next[p] <= p)进行匹配,
//然后再匹配时,后面的都整体后移了
p = next[p]; //拿到新的p值后,需要再次判断parttern[p]和text[t],相同就俩都后移,不同就继续查询next。不能t++
if(p == -1){//取到第一个了
p++;t++;
}
}
}
}
/**
* 取出 prefix数组
* @param parttern 需要求出前缀重复的str,len是parttern长度
* @return
*/
public static int[] prefixArray(char[] parttern,int len){
//前缀数组
int[] prefix = new int[len];
int n=0;
prefix[0] = 0;
for(int i=1;i<len;i++){
//取出当前位置 i-1 存储的prefix值
n = prefix[i-1];
if(parttern[i] == parttern[n]){
n++;
}else if(parttern[i] ==parttern[0]){
//如果和前面的prefix存储的值不一样了,看看和第一个是不是一样
n=1;
}else{
n=0;
}
prefix[i] = n;
}
return prefix;
}
/**
* 这个方法就是把prefix数组都后移一位,第一位下标是0的补上-1
* @param prefix
* @return
*/
public static int[] getNextArray(int[] prefix){
int[] next = new int[prefix.length];
next[0] = -1;
for(int i=0;i<prefix.length;i++){
if(i<prefix.length-1){
next[i+1] = prefix[i];
}
}
return next;
}
}