import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* <p>
* 计算模板串S在文本串T中出现了多少次
*
* @param T string字符串 模板串
* @param S string字符串 文本串
* @return int整型
*/
public int kmp(String T, String S) {
char[] sArr = S.toCharArray();
char[] tArr = T.toCharArray();
int s = 0;
int t = 0;
int count = 0;
int[] next = getNext(T);
System.out.println(Arrays.toString(next));
while (s < sArr.length) {
if (sArr[s] == tArr[t]) {
s++;
t++;
} else if (t == 0) {
s++;
} else {
t = next[t];
}
// 设虚拟串为T+' ' ,问题在S中匹配T转换为在S中匹配T+' '
// 当t == tArr.length时认为T+' '没有匹配到,但此时T已经匹配到,count++,
// 而T+' '则根据next数组继续回溯匹配
if (t == tArr.length) {
count++;
t = next[t];
}
}
return count;
}
private int[] getNext(String T) {
// 设len为T的长度,在原生KMP的next数组上加一个位置next[len],用于记录T[0]~T[len-1]的最长公共前缀长度
T = T + 'z';
char[] tArr = T.toCharArray();
int[] next = new int[tArr.length];
int i = 1;
int k = 0;
next[0] = -1;
while (i < tArr.length - 1) {
if (tArr[k] == tArr[i]) {
++i;
++k;
if (tArr[i] != tArr[k]) {
next[i] = k;
} else {
next[i] = next[k];
}
} else if (k == 0) {
next[++i] = 0;
} else {
k = next[k];
}
}
return next;
}
}