KMP算法Java实现
构造部分匹配表
部分匹配表的构建思路
// 获取部分匹配表
public static List<Integer> getPartialMatchingTable(String subString){
if(StringUtils.isEmpty(subString)){
return new ArrayList<>();
}
List<String> tempList = new ArrayList<>();
StringBuilder sb = new StringBuilder();
List<Integer> keyPairs = new ArrayList<>();
// 拆字符串 ABCDABD
// A AB ABC ABCD ABCDAB ABCDABD
for(int i=0;i<subString.length();i++){
sb.append(subString.charAt(i)+"");
tempList.add(sb.toString());
}
for(String str:tempList){
if(str.length()==1){
keyPairs.add(0);
continue;
}
StringBuilder leftSb = new StringBuilder();
StringBuilder rightSb = new StringBuilder();
int count = 0;
for(int i=0;i<str.length()-1;i++){
leftSb.append(str.charAt(i)+"");
rightSb.insert(0,str.charAt(str.length()-1-i)+"");
if(leftSb.toString().equals(rightSb.toString())){
count = leftSb.length();
}
}
keyPairs.add(count);
}
return keyPairs;
}
给定主串和子串,获取到满足条件的索引位置
public static int getfirstIndex(String source,String subString,Map<Integer, Integer> partialMatchingTableMap){
int index = -1;
if(source.isEmpty()||subString.isEmpty()||source.length()<subString.length()){
return index;
}
int subStringIndex = -1;
int firstMatchIndex = -1;
boolean firstMathch = true;
for(int i=0;i<source.length();i++){
if((source.charAt(i)+"").equals((subString.charAt(subStringIndex+1)+""))){
if(firstMathch){
firstMatchIndex = i;
firstMathch = false;
}
// 找到了,更新匹配的在substirng中的位置
subStringIndex++;
// 完成匹配
if(subStringIndex == subString.length()-1){
return firstMatchIndex;
}
}else if(!firstMathch){ // 匹配过的走这里
// 移动位数 = 已匹配的字符数 - 对应的部分匹配值
// 不匹配,查看需要往回倒的长度
int step = (subStringIndex+1) - partialMatchingTableMap.get(subStringIndex);
// 新位置开始,相关参数置空
i = firstMatchIndex+step;
subStringIndex = -1;
firstMathch = true;
firstMatchIndex = -1;
// i重置,此次索引不要动
i--;
}
}
return index;
}
测试结果
public static void main(String[] args) {
String source = "BBC ABCDAB ABCDABCDABDE";
String subString = "ABCDABD";
// 获取部分匹配表
List<Integer> partialMatchingTable = getPartialMatchingTable(subString);
Map<Integer, Integer> partialMatchingTableMap = new HashMap<>();
for(int i=0;i<partialMatchingTable.size();i++){
partialMatchingTableMap.put(i,partialMatchingTable.get(i));
System.out.print(i+" ");
}
System.out.println();
for(int i=0;i<partialMatchingTable.size();i++){
System.out.print(partialMatchingTable.get(i)+" ");
}
// 查找初次匹配的主串位置
int i = getfirstIndex(source, subString, partialMatchingTableMap);
System.out.println();
System.out.println("主串:"+source);
System.out.println("子串:"+subString);
System.out.println(subString+"在"+source+"中"+"匹配到的位置在主串中是: "+i);
}