代码随想录算法训练营第九天 |28. 找出字符串中第一个匹配项的下标、459. 重复的子字符串

67 阅读1分钟

代码随想录算法训练营第九天 |28. 找出字符串中第一个匹配项的下标、459. 重复的子字符串

KMP

  • 前缀表中遇见冲突的时候要根据其回退
  • 遇到冲突,移动到next数组前一位的位置。

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

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

  •  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要保证大于0,因为下面有取j-1作为数组下标的操作
                     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;
             // search部分
             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;
         }
     };
    

459. 重复的子字符串

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

  •  class Solution {
     public:
         bool repeatedSubstringPattern(string s) {
             int len = s.size();
             for(int i = 1 ; i*2 <= len; i++) {
                 if(len % i == 0) {
                     bool match = true;
                     for(int j = i; j < len; j++) {
                         if(s[j] != s[j - i]) {
                             match = false;
                             break;
                         }
                     }
                     if(match) {
                         return true;
                     }
                 }
             }
             return false;
         }
     };
    
  • 暴力法:

    • 如果要重复必须满足s[j] == s[j - i]
  • KMP:

  • 移动匹配

    • 当然,我们在判断 s + s 拼接的字符串里是否出现一个s的的时候,要刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s。