package com.mzs.testThread1;
public class TestDemo {
/**
* KMP核心:获取next数组,(本方法为其中的一种)
* 数组的每个元素是从0位到该元素下标位的最大前缀后缀的字符串长度
* @param str 模式字符串
* @return next数组
*/
private static int[] getNextArray(String str) {
char[] array = str.toCharArray(); // 定义模式字符串数组
int[] nextArray = new int[str.length()]; // 定义next数组
nextArray[0] = 0; // 设置next数组第一个元素为0(数学逻辑:必须为0)
int tOrder = 1; // 从下标为1开始计算数组元素值
int maxPreSuf = 0; // 前缀后缀字符串相同时的最大长度,(其实就是模式字符串匹配的长度)
while (tOrder < str.length()) {
while (maxPreSuf > 0 && array[maxPreSuf] != array[tOrder]) // (maxPreSuf没在起始位置,且失配时)
maxPreSuf = nextArray[maxPreSuf - 1]; // (算法核心):回溯到索引为上一个最大前缀后缀长度的next数组元素值处
if (array[maxPreSuf] == array[tOrder]) // 匹配时
maxPreSuf++;
nextArray[tOrder] = maxPreSuf; // 模式字符串数组从0到tOrder,这个字符串的匹配的长度也就是next数组的元素值
tOrder++;
}
return nextArray;
}
/**
* KMP算法
* @param str 主字符串
* @param str1 模式字符串
*/
private static void getKMP(String str, String str1) {
char[] array = str.toCharArray(); // 主字符数组
char[] array1 = str1.toCharArray(); // 模式字符数组
int[] nextArray = getNextArray(str1); // 获取模式字符串的next数组
int sOrder = 0; // 模式字符数组起始下标,(也就是模式字符串匹配的长度)
for (int i = 0; i < str.length(); i++) {
while (sOrder > 0 && array[i] != array1[sOrder]) // 下标没在初始位置,且失配时
sOrder = nextArray[sOrder - 1]; // 回溯到索引为上一个sOrder的next数组的位置处
if (array[i] == array1[sOrder]) // 匹配时
sOrder++;
if (str1.length() == sOrder) { // 完全匹配时
System.out.println("succeed to find at " + (i - sOrder + 1)); // 输出模式字符串的第一个字符在主字符串的位置
return ;
}
}
System.out.println("no matching, fail to find"); // 输出没有匹配到
}
public static void main(String[] args) {
String str = "abcdababaabababcacbaccfabfcdabcdf";
String str1 = "abababca";
getKMP(str, str1);
int[] array = getNextArray(str1);
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
}
算法 - KMP算法
猜你喜欢
转载自blog.csdn.net/qq_34561892/article/details/83869762
今日推荐
周排行