(9/60)实现strStr()、重复的子字符串

实现strStr

暴力遍历法

思路

双层循环,第一层遍历原字符串,第二层同时遍历寻找的字符串,一旦不匹配时,第一层退回到起始字符的下一位重新开始遍历。

复杂度分析

时间复杂度:最差时O(N^M)。最差情况每个寻找字符到最后一个字符不匹配,操作次数为原字符串长度N*寻找字符长度M。

空间复杂度:O(1)。

注意点

代码实现

class Solution {
public:
    int strStr(string haystack, string needle) {
        int p1 = 0;
        int p2 = 0;
        int index = -1;
        while(p1 < haystack.size()){
            if(haystack[p1] == needle[p2]){
                index = p1; // 记录下标
                while(p2 < needle.size()){
                    if(haystack[p1++] != needle[p2++]){
                        p2 = 0;
                        p1 = index; // 因为后面p1会++,取到index就可以了
                        index = -1;
                        break;
                    }
                }
            }

            p1++;   // 注意这里
        }

        return index;
    }
};

KMP算法

思路

算法思想是利用字符串最大公共前后缀(我觉得叫最大“周期”前后缀更易理解,强调是从左到右的匹配相等),来减少重复比对。

在操作上,核心就是“不匹配,j回退”(while(j > 0 && s[j] != s[i]) j = next[j - 1];),而i不回退,一直后移。(i对应haystack或needle,j对应needle)。

  1. 获取neddle的next数组。
  2. 遍历haystack,needle不匹配就j回退。
  3. 遍历到字符串末尾就结束。

复杂度分析

时间复杂度:O(N+M)。

  1. 获取 next 数组的复杂度为 O(n),其中 n 是模式串的长度。
  2. 在主循环中,需要遍历主串 haystack 的每个字符,时间复杂度为 O(m),其中 m 是主串 haystack 的长度。
  3. 对于每个字符,进行最多 j 次比较,其中 j 是当前匹配的字符数。在最坏情况下,j 最大为模式串 needle 的长度,因此最多进行 O(n) 次比较。

综上所述,整个算法的时间复杂度为 O(m + n),其中 m 是主串 haystack 的长度,n 是模式串 needle 的长度。空间复杂度为 O(n),用于存储 next 数组。

空间复杂度:O(N)。模式串长度N的前缀表。

注意点

代码实现

class Solution {
public:
    // KMP算法
    // 获取next数组
    vector<int> getNext(string& s){
        vector<int> next(s.size(),0);
        // 初始化
        next[0] = 0;
        int j = 0;
        for(int i = 1;i < s.size() && j < s.size();i++){
            // 不匹配,j回退
            while(j > 0 && s[j] != s[i]){
                j = next[j - 1];
            }
            // 匹配
            if(s[j] == s[i]) j++;
            // next赋值
            next[i] = j;
        }

        return next;
    }

    int strStr(string haystack, string needle) {
        vector<int> next = getNext(needle);
        int j = 0;
        // =size的时候说明末端匹配了,i、j都到了.end()位置
        // 进入循环直接触发if返回下标。
        for(int i = 0;i <= haystack.size();i++){    
            if(j >= needle.size())
                return i - needle.size();
            // 不匹配,j回退
            while(j > 0 && haystack[i] != needle[j]){
                j = next[j - 1];
            }
            // 匹配
            if(haystack[i] == needle[j]) j++;
        }

        return -1;
    }
};

重复的子字符串

leetcode:459. 重复的子字符串

暂时跳过!

posted @ 2024-02-02 02:19  Tazdingo  阅读(2199)  评论(0)    收藏  举报