• 稀碎从零算法笔记Day12-LeetCode:找出字符串中第一个匹配项的下标


    题型:字符串、字符串匹配算法

    链接:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

    来源:LeetCode

    题目描述

    给你两个字符串 haystack 和 needle ,请你在 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  (这里有个坑:不能保证haystack比needle长!)
    • haystack 和 needle 仅由小写英文字符组成

    题目思路

    两种思路:暴力开撕 或者 字符串匹配算法(比如KMP算法)

    暴力:笔者这里开了一个新的字符串temp来存haystack的前n个字符(假设n是needle.length()-1),然后看看temp和needle是否相等:相等就return i,不相等就让 i 右移

    字符串匹配算法(施工完毕!)

    KMP算法:重点:算法实现构建Next数组
    这里先说一下KMP算法中的next数组:其存储的是【最长相等前后缀的长度】
    手写起来还是很简单的,关键是代码实现。
    我的思路:双指针 i 和 j :其中 i 指向后缀的最后一位,j 有两重含义:① j 是最长前缀的长度 ② j 指向前缀的最后一位

    然后就是判断最长相等前后缀:

     

    感觉讲起来会很费劲,模拟一下代码的制行过程可能更好理解 

    C++代码

    暴力code:

    注意index越界

    1. class Solution {
    2. public:
    3. int strStr(string haystack, string needle) {
    4. // 暴力
    5. string temp;
    6. if(haystack.length()length())//被匹配串比匹配串短,-1
    7. return -1;
    8. else
    9. for(int i=0;i<=haystack.length()-needle.length();i++)
    10. {
    11. temp="";//空串
    12. for(int j=i;jlength();j++)//一次循环次数应该是匹配串的长度-1
    13. {
    14. temp.push_back(haystack[j]);
    15. }
    16. if(temp==needle)
    17. {
    18. return i;
    19. }
    20. }
    21. return -1;
    22. }
    23. };

     KMP算法:

    1. class Solution {
    2. public:
    3. int strStr(string haystack, string needle) {
    4. // KMP算法
    5. //重点:求模式串前缀表 构建next数组
    6. int lenH=haystack.length(),lenN=needle.length();//文本串的长度 模式串的长度
    7. int j=0;//j是①前缀的最后一位 ②最长相等前后缀的长度
    8. vector<int> next(lenN);//next数组,长度为
    9. next[0]=0;
    10. // 构建next数组
    11. for(int i=1;i//i是后缀的最后一位
    12. {
    13. while(j>0 && needle[j] != needle[i])
    14. {
    15. j=next[j-1];//前后缀不相等,j就移动到i的前一位的next处
    16. }
    17. if(needle[i]==needle[j])
    18. {
    19. j++;
    20. }
    21. next[i]=j;//因为j是最长相等前后缀的长度
    22. }
    23. for(int i=0,j=0;i
    24. {
    25. while(haystack[i] != needle[j] && j>0)
    26. {
    27. j=next[j-1];
    28. }
    29. if(haystack[i] == needle[j])
    30. j++;
    31. if(j==lenN)//遍历完了模式串,表示haystack中有needle
    32. return i-lenN+1;
    33. }
    34. return -1;
    35. }
    36. };

    结算页面

     

  • 相关阅读:
    狂神——SpringSecurity入门例子(设置不同用户访问权限)
    LeakyReLU激活函数
    优雅的处理POST请求URL带参数的情况
    C++模板元模板实战书籍讲解第一章题目讲解
    积分专题笔记-积分的定义
    Qt 目录操作(QDir 类)及展示系统文件实战 & QFilelnfo 类介绍和获取文件属性项目实战
    ArcGIS API4.X + API文档 本地部署(Tomcat)
    数据分表Mybatis Plus动态表名最优方案的探索
    Git下载,安装,提交
    推荐一个react拖拽排序的库,@dnd-kit
  • 原文地址:https://blog.csdn.net/m0_63356844/article/details/136574158