算法训练Day9:28. 实现 strStr(), 459.重复的子字符串,KMP

文章目录

  • 找出字符串中第一个匹配项的下标
    • 暴力解
    • 大佬的KMP解法
    • [参考大佬的文章讲的很细,还有视频]([代码随想录 (programmercarl.com)](https://programmercarl.com/0028.实现strStr.html))
  • 重复的子字符串
    • 题解1([移动匹配]([代码随想录 (programmercarl.com)](https://programmercarl.com/0459.重复的子字符串.html#移动匹配)))
    • 官方原文文档(npos)
      • std::basic_string::npos
      • 注意
    • 题解2(KMP)

找出字符串中第一个匹配项的下标

Category Difficulty Likes Dislikes ContestSlug ProblemIndex Score
algorithms Medium (42.17%) 1794 0 - - 0
Tags

Companies

给你两个字符串 haystackneedle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1

示例 1:

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。

示例 2:

输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。

提示:

  • 1 <= haystack.length, needle.length <= 104
  • haystackneedle 仅由小写英文字符组成

Discussion | Solution

暴力解

class Solution {
public:
    int strStr(string haystack, string needle) {
        int n = haystack.size(), m = needle.size();
        for (int i = 0; i + m <= n; i++) {
            bool flag = true;
            for (int j = 0; j < m; j++) {
                if (haystack[i + j] != needle[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return i;
            }
        }
        return -1;
    }
};

大佬的KMP解法

class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = 0;
        for(int i = 1; i < s.size(); i++) {
            while (j > 0 && s[i] != s[j]) {
                j = next[j - 1];
            }
            if (s[i] == s[j]) {
                j++;
            }
            next[i] = j;
        }
    }
    int strStr(string haystack, string needle) {
        if (needle.size() == 0) {
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while(j > 0 && haystack[i] != needle[j]) {
                j = next[j - 1];
            }
            if (haystack[i] == needle[j]) {
                j++;
            }
            if (j == needle.size() ) {
                return (i - needle.size() + 1);
            }
        }
        return -1;
    }
};

[参考大佬的文章讲的很细,还有视频](代码随想录 (programmercarl.com))

重复的子字符串

Category Difficulty Likes Dislikes ContestSlug ProblemIndex Score
algorithms Easy (51.14%) 924 0 - - 0
Tags

字符串 | 字符串匹配

Companies

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

Discussion | Solution

题解1([移动匹配](代码随想录 (programmercarl.com)))

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        string t = s + s;
        t.erase(t.begin());t.erase(t.end()-1);
        if(t.find(s) != std::string::npos ) return true;
        return false;
    }
};

官方原文文档(npos)

std::basic_string::npos

C++

字符串库

标准::basic_string

静态常量 size_type NPOS = -1;

这是一个特殊值,等于 类型 表示的最大值。确切的含义取决于上下文,但它通常由期望字符串索引的函数用作字符串指示符的末尾,或由返回字符串索引的函数用作错误指示符。size_type

注意

虽然定义使用-1,size_type 是无符号整数类型,由于有符号到无符号的隐式转换,其值是它可以容纳的最大正值。这是一种可移植的方法,用于指定任何无符号类型的最大值。npos

运行此代码

#include 
#include 
#include 
 
int main()
{
    // string search functions return npos if nothing is found
    std::string s = "test";
    if(s.find('a') == std::string::npos)
        std::cout << "no 'a' in 'test'\n";
 
    // functions that take string subsets as arguments 
    // use npos as the "all the way to the end" indicator
    std::string s2(s, 2, std::string::npos);
    std::cout << s2 << '\n';
 
    std::bitset<5> b("aaabb", std::string::npos, 'a', 'b');
    std::cout << b << '\n';
}

输出:

no 'a' in 'test'
st
00011

题解2(KMP)

class Solution {
public:
    void getNext (int* next, const string& s){
        next[0] = 0;
        int j = 0;
        for(int i = 1;i < s.size(); i++){
            while(j > 0 && s[i] != s[j]) {
                j = next[j - 1];
            }
            if(s[i] == s[j]) {
                j++;
            }
            next[i] = j;
        }
    }
    bool repeatedSubstringPattern (string s) {
        if (s.size() == 0) {
            return false;
        }
        int next[s.size()];
        getNext(next, s);
        int len = s.size();
        //数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。
        if (next[len - 1] != 0 && len % (len - (next[len - 1] )) == 0) {
            return true;
        }
        return false;
    }
};

你可能感兴趣的:(字符串,算法训练,算法,leetcode)