代码随想录算法训练营第九天 | 28. 实现 strStr(),459.重复的子字符串,字符串总结,双指针回顾

28. 实现 strStr()

题目链接:28. 找出字符串中第一个匹配项的下标

思路

该题是KMP算法的实现,分两步走:

(1)构造next数组;

(2)利用next数组求解匹配情况;

这两步也大致相同都是:

① 循环处理不匹配情况;② 处理匹配情况;③ 更新next数组/处理结果;

代码实现

class Solution {
public:
    int strStr(string haystack, string needle) {
        // 求next数组
        int next[needle.size()];
        // 初始化
        int j = 0;
        next[0] = j;
        for(int i = 1; i < needle.size(); ++i){
            // 不匹配,回退
            while(j > 0 && needle[j] != needle[i])  j = next[j-1];
            // 匹配
            if(needle[j] == needle[i])  ++j;
            // 更新
            next[i] = j;
        }
        j = 0;
        for(int i = 0; i < haystack.size(); ++i){
            while(j > 0  && needle[j] != haystack[i]) j = next[j-1];
            if(needle[j] == haystack[i]){
                ++j;
            }
            if(j >= needle.size())  return i - j + 1;
        }
        return -1;
    }
};

小结

KMP算法的应用:解决某字符串是否在零一字符串中出现过,关键是构造和利用next数组,next数组的本质是最长相等前后缀的长度

459.重复的子字符串

题目链接:459. 重复的子字符串

思路与代码实现

暴力求解

一重for循环确定子串(只用确定子串尾部,子串头部一定从字符串首字符开始),一重for循环匹配子串与原串;

移动匹配

只用一重for循环来确定子串的尾部,将字符串 s 复制到尾部成 s + s,若字符串 s 是由它的一个子串重复多次构成,则 s + s 中间(除去两头)一定能凑出 s:

代码随想录算法训练营第九天 | 28. 实现 strStr(),459.重复的子字符串,字符串总结,双指针回顾_第1张图片

KMP算法

求重复的子字符串,可以看作是求最长相等前后缀所不包含的部分,判断其是否构成重复子字符串。

代码随想录算法训练营第九天 | 28. 实现 strStr(),459.重复的子字符串,字符串总结,双指针回顾_第2张图片

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int size = s.size();
        int next[size];
        int j = 0;
        next[0] = j;
        for(int i = 1; i < size; ++i){
            while(j > 0 && s[j] != s[i])    j = next[j-1];
            if(s[j] == s[i])    ++j;
            next[i] = j;
        }
        int ans = size % (size - next[size-1]);
        if(!ans && next[size-1] > 0)    return true;
        else    return false;
    }
};

小结

涉及最长公共前后缀的问题,考虑使用KMP算法的思路求解。

字符串总结 

字符串这一块主要的问题:(1)填充数组类问题(2)反转类问题;(3)子串类问题;

遇到反转类问题,考虑局部反转与整体反转结合的思路;遇到子串类问题,考虑是否与匹配相关,涉及最长相等前后串的问题考虑KMP算法。

这一块主要有两个重要求解思想/算法:双指针思想、KMP算法。

另外:

很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

双指针回顾 

27. 移除元素

344. 反转字符串

LCR 122. 路径加密

151. 反转字符串中的单词

206. 反转链表

19. 删除链表的倒数第 N 个结点

面试题 02.07. 链表相交

142. 环形链表 II

15. 三数之和

18. 四数之和

你可能感兴趣的:(算法)