28. 找出字符串中第一个匹配项的下标
- 题目链接:28. 找出字符串中第一个匹配项的下标
- 解题思路:第一想法肯定是两层for循环遍历,时间复杂度是O(m*n),这个题本身考的是KMP算法,对这块不太熟,头一次接触,看了两个讲解视频之后写了一种前缀表不变的解法,但是感觉有些还是没理解。
- 主要难点:KMP算法 难
- 解题步骤:
- 需要先定义一个函数用来求字符串的前缀表next数组,数组里放的是这个字符串每个位置上的最大前后缀相同长度,在这个函数中需要处理前后缀相等和前后缀不相等两种情况,当前后缀不相等的时候,j需要进行回退,回退的位置的当前j所在位置前一个位置对应的next数组值,当j已经回退到头时就不再回退了,而当前后缀相等的时候,填充next数组并把j向后移动
- 在主函数中先定义一个和子串长度相同的数组,并调用上述函数生成这个子串的前缀表
- 然后开始比较两个字符串,当出现不匹配的时候,去查这个位置前一个位置对应的前缀表,找他最长的前后缀相等值,然后以这个值为下标重新开始比对。
- 解题时间:60+5
- 代码:
class Solution {
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 && needle.charAt(j) != haystack.charAt(i)){
j = next[j-1];
}
if(needle.charAt(j) == haystack.charAt(i)){
j++;
}
if(j == needle.length()){
return i-needle.length()+1;
}
}
return -1;
}
private 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(j) != s.charAt(i)){
j = next[j-1];
}
if(s.charAt(j) == s.charAt(i)){
j++;
}
next[i]=j;
}
}
}
459. 重复的子字符串
- 题目链接:459. 重复的子字符串
- 解题思路:可以用循环暴力求解,但是这个题也可以使用KMP算法来做,KMP算法针对的就是字符串子串问题,重复的子字符串也算是子串。因为 最长相等前后缀的规则,当一个字符串由重复子串组成的,最长相等前后缀不包含的子串就是最小重复子串。
- 主要难点:KMP算法,怎么确定最小的循环?
- 解题时间:30+5
- 代码:
class Solution {
public boolean repeatedSubstringPattern(String s) {
if (s.equals("")) return false;
int len = s.length();
s = " " + s;
char[] chars = s.toCharArray();
int[] next = new int[len + 1];
for (int i = 2, j = 0; i <= len; i++) {
while (j > 0 && chars[i] != chars[j + 1]) j = next[j];
if (chars[i] == chars[j + 1]) j++;
next[i] = j;
}
if (next[len] > 0 && len % (len - next[len]) == 0) {
return true;
}
return false;
}
}
总结
- 字符串总结
- 库函数的使用:需要熟悉自己语言里一些库函数的实现和应用方法,但是也不应该过于依靠库函数,有的时候也需要自己实现库函数的功能,例如:split分割,reverse反转,substr子字符串等等
- 双指针法的应用:有的时候一眼看上去的暴力揭发是两层循环嵌套的时候,或者需要新建额外空间实现的时候,可以想一下能不能用双指针方法减少一层循环,或是减少额外空间消耗做到原地实现。
- KMP:KMP算法作为一种专门解决字符串子串问题的方法,在字符串部分用的比较多,整体思想可能比较难懂,需要后面二刷的时候重新看,不光是背模板,要理解每一步的思路。KMP算法的主要思想就是当字符串不匹配的时候,不再从头重新比,而是想办法用上之前已经查过的结果,减小比较次数。核心是前缀表的思路和设置,难点是找到最后解题需要什么