首页 > 编程语言 >代码训练营第22天|补第9天的KMP算法,28. 找出字符串中第一个匹配项的下标|459.重复的子字符串

代码训练营第22天|补第9天的KMP算法,28. 找出字符串中第一个匹配项的下标|459.重复的子字符串

时间:2024-10-23 17:20:56浏览次数:6  
标签:补第 匹配 22 int needle next 数组 字符串 size

前置知识

文章链接:https://programmercarl.com/0028.实现strStr.html#思路

  • KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。
  • 前缀表:next数组就是一个前缀表(prefix table)。前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配。next数组也可以是前缀表加一之后的结果,方便进行代码的实现。

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

题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/
视频链接:https://www.bilibili.com/video/BV1PD4y1o7nd/

KMP算法:

总结:此题分两部分:先求next数组,接着进行匹配。

  1. 以下next数组的求法中,我将j=0,i=1;并设每一个数组元素表示除这个元素之外的前面的数组的最长公共前后缀
    所以next[0]=-1;next[1]=0是固定的
    关于怎么求next数组推荐:https://www.youtube.com/watch?v=GTJr8OvyEVQ
  2. 在文本串和模式串匹配的过程中,文本串是一个一个的向后移动并进行比较的,所以时间复杂度是n,加上模式串求解next数组的时间复杂度m,所以总的时间复杂度为O(m+n)
class Solution {
public:
    vector<int> getNext(string needle){
        int j=0;
        int len=needle.size();
        vector<int> next;
        //初始化,next前两个元素值是固定的(next元素值表示除它之外前面子数组的最大公共前后缀)
        next.push_back(-1);
        next.push_back(0);
        for(int i=1;i<len-1;i++){
            //当前后缀不相等,j向后回退
            while(j>0&&needle[j]!=needle[i]){
                j=next[j];//回到当前j所指向的next数组元素值对应的下标处
            }
            if(needle[j]==needle[i]) j++;
            next.push_back(j);
        }
        return next;
    }

    int strStr(string haystack, string needle) {
        vector<int> next=getNext(needle);
        int res=-1;
        int lenH=haystack.size();
        int lenN=needle.size();
        int i=0,j=0;
        //出口为,既没有匹配成功,i也到了lenH
        for(i;i<lenH;i++){
            //不匹配,j回退,直到j=0或匹配为止
            while(j>0&&haystack[i]!=needle[j]){
                j=next[j];
            }
            //匹配的时候,j++
            if(haystack[i]==needle[j]) j++;
            //一旦出现了j=lenN,说明匹配成功,此时还没有i++
            if(j==lenN) {
                res=i-j+1;
                return res;
            }
        }
        return res;
    }
};

459.重复的子字符串

文章链接:https://programmercarl.com/0459.重复的子字符串.html#算法公开课
视频链接:https://www.bilibili.com/video/BV1cg41127fw
题目链接:https://leetcode.cn/problems/repeated-substring-pattern/description/

方法一:移动匹配
s + s ,并刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s。
方法二:KMP算法
要点:最长前后缀剩余部分即可能为最小重复子串(剩余部分不可比s的一半的长度还大)
另外,如果剩余部分不可整除s,则说明也没有最小重复子串
例如:

由于这个题在解决的函数中需要用到前缀表,所以对于右移一位的next数组,最好不右移,直接使用前缀表表示的next数组。

class Solution {
public:
    vector<int> getNext(string s){
        int j=0,i=1;
        vector<int> next;
        //初始化next数组的头元素值(固定的)
        next.push_back(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.push_back(j);
        }
        return next;
    }
    bool repeatedSubstringPattern(string s) {
        vector<int> next=getNext(s);
        int size=next.size();
        int remain=size-next[size-1];
        //如果没有公共前后缀,或remain整除s,则false
        if(next[size-1]==0||size%remain!=0) return false;
        return true;
    }
};

标签:补第,匹配,22,int,needle,next,数组,字符串,size
From: https://www.cnblogs.com/VickyWu/p/18457756

相关文章

  • 字符串的切分及其拓展
    假如有以下email数据“[email protected],[email protected],[email protected],..”现需要把email中的用户部分和邮件地址部分分离,分离后以键值对应的方式放入HashMap思路:我们要将Email的用户部分和邮件地址部分分离,分离后以键值对应的方式放入HashMap,要思考一下怎么将一整个字符变为aa......
  • 20222316 2024-2025-1 《网络与系统攻防技术》实验二实验报告
    一、实验内容1.学习总结——后门与免杀1)后门基本概念后门就是不经过正常认证流程而访问系统的通道。狭义后门:特指潜伏于操作系统中专门做后门的一个程序,“坏人”可以连接这个程序,远程执行各种指令。后面类型有编译器后门、操作系统后门、应用程序后门、潜伏于操作系统中或......
  • 20222324 石国力 《网络与系统攻防技术》 实验二
    1.实验内容(1)使用netcat获取主机操作Shell,cron启动某项任务(2)使用socat获取主机操作Shell,任务计划启动(3)使用MSFmeterpreter(或其他软件)生成可执行文件(后门),利用ncat或socat传送到主机并运行获取主机Shell(4)使用MSFmeterpreter(或其他软件)生成获取目标主机音频、摄像头、......
  • 2024/10/22 模拟赛小记
    A.日期速算_date题意:给你一个日期,然后问k天之后日期。形式如“20240229”。保证年份在2000-9999年。看榜的时候发现挂掉了,有点迷惑。发现思路没什么问题。把cin,cout改成scanf和printf就过了。。?。什么oj特色。Code#include<bits/stdc++.h>usingnamespacest......
  • 20222310 2024-2025-1 《网络与系统攻防技术》实验三实验报告
    一、实验内容1.正确使用msf编码器,veil-evasion,自己利用shellcode编程等免杀工具或技巧(1)正确使用msf编码器,使用msfvenom生成如jar之类的其他文件(2)学会使用veil,加壳工具(3)能够使用C+shellcode编程2.通过组合应用各种技术实现恶意代码免杀成功实现了免杀的,简单语言描述原理,不......
  • 题解:CF1225E Rock Is Push
    很玄妙的一道dp题。HintAnalysis首先你要确保你会做当石头没有/固定的情况,这道题其实也是dp。考虑石头带来的影响,唯一的作用就是限制你的移动,比方说你下面有\(3\)块石头,由于只能向右或向下移动,你实际上往下只能走到当前列第\(n-3\)行。于是对于石头的处理,设\(rs[i][j......
  • 2022 International Collegiate Programming Contest, Jinan Site
    2022InternationalCollegiateProgrammingContest,JinanSiteK.StackSort题意给一个从1到n的排序,按顺序把这些数压入m个栈全部入栈后,每次选择一个栈,把数字全部弹出再换下一个要求弹出顺序是升序的思路发现要把\(x\)和\(x-1\)压入同一个栈,这样出栈才能按顺序可以......
  • 22年计挑赛Python组区域赛个人解答
    第一题:代码部分:生产问题A=100;B=150;List=[]a,b,c,d,e,f,g,h,i=map(int,input().split())list=[a,b,c,d,e,f,g,h,i]forminrange(min(g//a,h//b,i//c)+1):n=min((g-m*a)//e,(h-m*b)//f,(i-m*c)//f)w=A*m+B*nList.append(w);List.append(m);......
  • CRC32爆破脚本 + [MoeCTF 2022]cccrrc 题解
    CRC32爆破原理介绍:CRC(循环冗余校验)是一种用于检测数据传输错误的技术。CRC算法生成一个校验值(校验和),这个值可以附加到数据后面,在数据接收方重新计算校验值并与附加的校验值进行比较,以此来确定数据是否在传输过程中发生了错误CRC32是一种常用的CRC算法,它的校验值长度固定为3......
  • P8816 [CSP-J 2022] 上升点列 题解
    最长上升子序列根据题目中,每个坐标的横纵坐标均单调递增,所以明显可以使用最长上升子序列.定义状态$f_{i,p}$,表示正在节点$i$时,还剩下$p$次插入机会,所能达到的最大长度.定义变量$dis=|x_i-x_j|+|y_i-y_j|-1.$,表示$i$到$j$节点至少要插$dis$个节点.为什么要$-1$......