day8:字符串part2,KMP算法
参考:
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
KMP算法关键点记忆:
s 原字符串
p 匹配串
j+1 表示:前缀末尾位置
j 同时表示:当前最长相等前后缀长度
i 表示:后缀末尾位置
next数组值含义:当前最长相等前后缀长度
28.找出字符串中第一个匹配项的下标
class Solution {
public int strStr(String haystack, String needle) {
int n = haystack.length(), m = needle.length();
// 原串和匹配串前面都加空格,使其下标从 1 开始
String ss = " " + haystack;
String pp = " " + needle;
char[] s = ss.toCharArray();
char[] p = pp.toCharArray();
int[] next = new int[m + 1];
// 求next数组 step1:不相等情况 step2:相等情况 step3:设置next数组值
// i, j是下标,本来应该从1开始
// i从2开始是因为1位置的next数组值肯定为0
// j从0开始是因为j同时还表示相同前后缀长度值
for (int i = 2, j = 0; i <= m; i++) {
while (j > 0 && p[i] != p[j + 1]) j = next[j];
if (p[i] == p[j + 1]) j++;
next[i] = j;
}
// i从1开始是因为要从头开始匹配原串了
for (int i = 1, j = 0; i <= n; i++) {
while (j > 0 && s[i] != p[j + 1]) j = next[j];
if (s[i] == p[j + 1]) j++;
if (j == m) return i - m;
}
return -1;
}
}
459.重复的子字符串
class Solution {
public boolean repeatedSubstringPattern(String s) {
int n = s.length();
s = " " + s;
char[] ss = s.toCharArray();
int[] next = new int[n + 1];
for (int i = 2, j = 0; i <= n; i++) {
while (j > 0 && ss[i] != ss[j + 1]) j = next[j];
if (ss[i] == ss[j + 1]) j++;
next[i] = j;
}
if (next[n] > 0 && n % (n - next[n]) == 0) return true;
return false;
}
}