KMP练习题
LeetCode链接:459. 重复的子字符串
1.题目描述
给定一个非空的字符串 s
,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
1 2 3
| 输入: s = "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。
|
示例 2:
示例 3:
1 2 3
| 输入: s = "abcabcabcabc" 输出: true 解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)
|
提示:
- $1 <= s.length <= 10^4$
s
由小写英文字母组成
2.题解
2.1 暴力解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public boolean repeatedSubstringPattern(String s) { int n = s.length(); for(int i = 1; i <= n / 2; i++) { if(n % i == 0) { int j; for(j = i; j < n; j++) { if(s.charAt(j) != s.charAt(j - i)) break; } if(j == n) return true; } } return false; } }
|
2.2 KMP - 移动匹配
2.2.1 内置函数
1 2 3 4 5 6 7 8
| class Solution { public boolean repeatedSubstringPattern(String s) { return (s + s).indexOf(s, 1) != s.length(); } }
|
2.2.2 KMP实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| class Solution { public boolean repeatedSubstringPattern(String s) { int n = s.length(); String goal = s; s = s + s; int[] next = getNext(goal); int j = 0;
for (int i = 1; i < n * 2 - 1; i++) { while (j > 0 && s.charAt(i) != goal.charAt(j)) j = next[j - 1]; if (s.charAt(i) == goal.charAt(j)) j++; if (j == n) return true; }
return false; } public int[] getNext(String s) { int n = s.length(); int[] next = new int[n]; int j = 0; next[0] = 0;
for (int i = 1; i < n; 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; } return next; } }
|
2.3 KMP优化
- 这个方法需要对种字符串的
next
数组的特征要了解,毛毛张在下面举几个例子
- 正例: 字符串
abababab
的next
数组:[0, 0, 1, 2, 3, 4, 5, 6]
- 正例: 字符串
ababcababcababc
的next
数组:[0, 0, 1, 2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- 反例: 字符串
abcabca
的next
数组:[0, 0, 0, 1, 2, 3, 4]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class Solution { public boolean repeatedSubstringPattern(String s) { int n = s.length(); int[] next = getNext(s); int minLen = n - next[n - 1]; if (minLen < n && n % minLen == 0) return true; return false; }
public int[] getNext(String s) { int n = s.length(); int[] next = new int[n]; int j = 0; next[0] = 0;
for (int i = 1; i < n; 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; } return next; } }
|