当前位置: 首页 > article >正文

[代码随想录] KMP 算法 28. 找出字符串中第一个匹配项的下标 459. 重复的子字符串

KMP目录

  • KMP 基础知识
    • 构建前缀表
    • 使用前缀表减少运算步骤
  • 28. 找出字符串中第一个匹配项的下标
  • 459. 重复的子字符串

KMP 基础知识

奇乐编程学院
https://www.bilibili.com/video/BV1AY4y157yL/?spm_id_from=333.1391.0.0
代码随想录
https://www.bilibili.com/video/BV1PD4y1o7nd?spm_id_from=333.788.videopod.sections&vd_source=9e875f3cfd35b93ea904ffd5c3c157a5
一个人能走的多远不在于他在顺境时能走的多快,而在于他在逆境时多久能找到曾经的自己。
————KMP

(复制的B站评论)

概述:使用前缀表来代替重复比较。
kmp算法关键在于:在当前对文本串和模式串检索的过程中,若出现了不匹配,如何充分利用已经匹配的部分。
主要步骤:

  1. 构建前缀表
  2. 遍历字符串,利用前缀表进行更新

构建前缀表

前缀不包含尾字母,一定包含首字母的所有子串。
后缀不包含首字母,一定包含尾字母的所有字串。
在构建前缀表的时候就使用了KMP思想。
在这里插入图片描述
在这里插入图片描述

使用前缀表减少运算步骤

前面i,j都是在同一个字符串下。求重复子串的时候,
KMP算法遇到不匹配的地方,可以直接跳到上一次匹配的地方继续匹配。
在这里插入图片描述

在这里插入图片描述

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

就是存在问题的基础上,如果遍历过程中遇到j==needle.size();直接返回return i-needle.size()+1;
下面注释了一个双指针法,两个指针遍历两个字符串,在没接触KMP时候写的。

class Solution {
public:
    void build_next(vector<int>& next, string s){
        next[0] = 0;
        int j = 0;//前缀的末尾
        for(int i = 1; i < s.size(); i ++){ //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.empty()) return 0;
        vector<int> next(needle.size());
        build_next(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;
    }
};
        // for(int i=0; i < haystack.size(); i++){
        //     int left = 0;
        //     if(needle[left]==haystack[i]){
        //         int right = i+1;
        //         left++;
        //         while(left<needle.size()){
        //             if(needle[left]!=haystack[right]) break;
        //             left++;
        //             right++;
        //         }
        //         if(left == needle.size()) return i;
        //     }
        // }
        // return -1;

459. 重复的子字符串

在这里插入图片描述

在这里插入图片描述

class Solution {
public:
    void build_next(vector<int>& next, string s){
        int j = 0;
        next[0] = 0;//初始化
        for(int i = 1; i < s.size(); i++){
            while(s[i]!=s[j] && j>0){
                j = next[j-1];//跳跃到下一个要比较的地方
            }
            if(s[i]==s[j]) next[i] = ++j;
        }
    }
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        vector<int> next(n);
        build_next(next, s);
        int len = next[n-1];
        return len > 0 && n % (n - len) == 0;
    }
};

http://www.kler.cn/a/614314.html

相关文章:

  • mac安装mongoDB的正确姿势
  • 智网安全:守护未来数字文明的基石
  • Vue3 配合 fullPage.js 打造高效全屏滚动网页
  • spring security认证流程分析
  • 对内核fork进程中写时复制的理解记录
  • 【Linux笔记】进程间通信——匿名管道||进程池
  • 智能仪表板DevExpress Dashboard v24.2新版亮点:支持.NET 9
  • 管理Visual Studio配置文件(使用Azure DevOps开发,免费GIT托管)
  • OpenAI API - 快速入门开发
  • 使用Python的pytesseract进行网站模拟登录的脚本,主要针对古诗文网(gushiwen.cn)的登录功能。
  • 图论问题集合
  • 加载MiniLM-L12-v2模型及知识库,调用Deepseek进行问答
  • 【Hysteria】部署+测试
  • 虚拟机docker配置ES
  • Docker:ERROR [internal] load metadata for docker.io/library/java:8-alpine问题解决
  • UDS故障码(DTC)SAE格式和HEX相互转换公式
  • B3647 【模板】Floyd
  • ubuntu 安装mysql
  • 【计算机网络】网络原理
  • 智能路由系统-信息泄露漏洞挖掘