package algorithm;
public class KmpSearch {
public static void main(String[] args) {
String s1 = "ABABCABAA";
char[] pattern = s1.toCharArray();
String s2 = "ABABABCABAACDEFSA";
char[] text = s2.toCharArray();
System.out.println("----------------------------------");
int[] prefix = new int[pattern.length];
int n = pattern.length;
prefix_table(pattern, prefix, n);
//输出prefix查看结果
System.out.println("往右移动之前");
for (int i = 0; i < prefix.length; i++) {
System.out.println(prefix[i]);
}
move_prefix_table(prefix, n);
System.out.println("往右移动之后");
for (int i = 0; i < prefix.length; i++) {
System.out.println(prefix[i]);
}
System.out.println("----------------------------------");
kmp_search(text, pattern);
}
/**
* 往右移动一位的prefix数组内容
* @param prefix prefix数组
* @param n 子串字符数组长度
*/
private static void move_prefix_table(int[] prefix, int n){
for (int i = n-1; i > 0; i--) {
prefix[i] = prefix[i-1];
}
prefix[0] = -1;
}
/**
*
* @param pattern 子串字符数组
* @param prefix prefix数组
* @param n 子串字符数组长度
*/
private static void prefix_table(char[] pattern, int[] prefix, int n){
prefix[0] = 0;
int len = 0;//最长公共长度
int i = 1;
while(i < n){
if(pattern[i] == pattern[len]){
len++;
prefix[i] = len;
i++;
}else{
if(len > 0){
len = prefix[len -1];
}else{
prefix[i] = len;
i++;
}
}
}
}
/**
* 在text长串中查找pattern子串
* @param text
* @param pattern
*/
private static void kmp_search(char[] text, char[] pattern){
//子串的长度
int n = pattern.length;
int[] prefix = new int[n];
//求出prefix
prefix_table(pattern, prefix, n);
move_prefix_table(prefix, n);
//text[i] len(text) = m;
//pattern[j] len(pattern) = n;
int i = 0,j = 0;
int m = text.length;
while(i < m){
if(j == n-1 && text[i] == pattern[j]){
System.out.println("Found pattern at "+(i - j));
j = prefix[j];
}
if(text[i] == pattern[j]){
i++;
j++;
}else{
j = prefix[j];
if(j == -1){
i++;
j++;
}
}
}
}
}