leetcode练习
28. 实现 strStr()
题目,在一个串中查找是否出现过另一个串,这是KMP的看家本领。KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
KMP求前缀表的固定代码模板:
public void getNext(int[] next, String s){
int j = 0;
next[0] = 0;
for (int i = 1; i < s.length(); i++){
while (j > 0 && s.charAt(i) != s.charAt(j)){
j = next[j - 1];
}
if (s.charAt(i) == s.charAt(j)){
j++;
}
next[i] = j;
}
}
求得前缀表后,根据前缀表计算出目标字符串出现的第一个字符的位置。
public int strStr(String haystack, String needle) {
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];
getNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.length(); i++){
while (j > 0 && haystack.charAt(i) != needle.charAt(j)){
j = next[j - 1];
}
if (haystack.charAt(i) == needle.charAt(j)){
j++;
}
if (j == needle.length()){
return i - needle.length() + 1;
}
}
return -1;
}
459.重复的子字符串
题目,数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。可以把next数组打印出来,看看next数组里的规律,有助于理解KMP算法
public boolean repeatedSubstringPattern(String s) {
if (s.length() == 0) return false;
int[] next = new int[s.length()];
getNext(next, s);
int n = s.length() - next[s.length() - 1];
if (next[s.length() - 1] != 0 && s.length() % n == 0 && next[s.length() - 1] % n == 0) return true;
return false;
}