KMP算法练习题
LeetCode链接:796. 旋转字符串
1.题目描述
给定两个字符串, s
和 goal
。如果在若干次旋转操作之后,s
能变成 goal
,那么返回 true
。
s
的 旋转操作 就是将 s
最左边的字符移动到最右边。
- 例如, 若
s = 'abcde'
,在旋转一次之后结果就是'bcdea'
。
示例 1:
1 2
| 输入: s = "abcde", goal = "cdeab" 输出: true
|
示例 2:
1 2
| 输入: s = "abcde", goal = "abced" 输出: false
|
提示:
1 <= s.length, goal.length <= 100
s
和 goal
由小写英文字母组成
2.题解
2.1 暴力解法
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
| class Solution { public boolean rotateString(String s, String goal) { if (s.length() != goal.length()) return false; char[] chs = s.toCharArray(); char[] cht = goal.toCharArray(); for (int i = 0; i < chs.length; i++) { char temp = chs[0]; for (int j = 0; j < cht.length - 1; j++) { chs[j] = chs[j + 1]; } chs[chs.length - 1] = temp; if (Arrays.equals(chs, cht)) return true; } return false; } }
|
2.2 模拟
- 上面我们是通过将字符串转换成字符数组,然后实际进行旋转,当时实际上并不需要,我们可以通过取模的方式来模拟旋转字符串,这种方法称为模拟
- 首先,如果$s$和$goal$的长度不一样,那么无论怎么旋转,$s$都不能得到$goal$,返回$false$。在长度一样(都为 n)的前提下,假设$s$旋转$i$位,则与$goal$中的某一位字符$ goal[j] $对应的原$s$中的字符应该为 $s[(i+j)\ mod\ n]$。在固定$i$的情况下,遍历所有$j$,若对应字符都相同,则返回$true$。否则,继续遍历其他候选的 $i$。若所有的$i$都不能使$s$变成$goal$,则返回 $false$
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 rotateString(String s, String goal) { if (s.length() != goal.length()) return false;
int len = s.length(); for (int i = 0; i < len; i++) { int j; for (j = 0; j < len; j++) { if (s.charAt((i + j) % len) != goal.charAt(j)) break; } if (j == len) return true; } return false; } }
|
2.3 字符串匹配 - 移动匹配
- 首先,如果 s 和 goal 的长度不一样,那么无论怎么旋转,s 都不能得到 goal,返回 false。字符串 s+s 包含了所有 s 可以通过旋转操作得到的字符串,只需要检查 goal 是否为 s+s 的子字符串即可。
2.3.1 内置函数
1 2 3 4 5
| class Solution { public boolean rotateString(String s, String goal) { return s.length() == goal.length() && (s+s).contains(goal); } }
|
2.3.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 39 40 41 42
| class Solution { public boolean rotateString(String s, String goal) { if (s.length() != goal.length()) return false;
s = s + s; int[] next = getNext(goal);
int j = 0; for (int i = 0; i < s.length(); i++) { while (j > 0 && s.charAt(i) != goal.charAt(j)) j = next[j - 1]; if (s.charAt(i) == goal.charAt(j)) j++; if (j == goal.length()) 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; } }
|