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

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

题目

 

思路 

  • 初步的思路是使用一个双指针,i遍历hay字符串,j遍历nee字符串,若在hay中找到了包含nee的部分,则输出(i-nlen+1);若有一个字母不匹配,则j从0开始、i继续往后遍历,直到找到首个匹配项的下标,或者i遍历到hlen末端

弊端:时间复杂度O(n^2) 

好处就是容易想到,好实现

  • 而后学习到可以用KMP算法做,即寻找next数组(最长相同前后缀)
  1. next/前缀表的用处:前缀表是用来回退的,它记录了模式串与主串(文本串)不匹配的时候,模式串应该从哪里开始重新匹配
  2. 什么是最长公共前后缀,如何通过最长公共前后缀得到next数组? 

对KMP算法的详细解释 代码随想录 (programmercarl.com)

实现:

 

简单的思路:

 

代码(不减一): 

// 找到needle不减一的前缀表
    int j=0;
    int *next=(int*)malloc(sizeof(int)*nlen);
    next[0]=j;
    for(int i=1;i<nlen;i++)
    {
        // 当被判断的字符串长度不为1.且前后缀不相同时
        while(j>0&&needle[j]!=needle[i])j=next[j-1];//直至找到相同前后缀,或者字符串 遍历完成

        // 当前后缀相同时
        if(needle[j]==needle[i])j++;//j指针右移一位

        // 把j的值(前缀长度)赋给前缀表中对应的i
        next[i]=j;
    }

 

  •  用next数组来做匹配(用图来理解)

不匹配时,找到原来匹配的位置 

 

 代码:

// 用next表做haystack和needle的匹配
    j=0;
    for(int i=0;i<hlen;i++)//注意i此时时用于遍历haystack字符串的指针,从0开始
    {
        //若两个字母不匹配时
        while(j>0&&needle[j]!=haystack[i])j=next[j-1];//j 寻找之前匹配的位置
        
        //若两个字母匹配时
        if(needle[j]==haystack[i])j++;

        //若hay字符串中出现了nee完整的字符串(j遍历到最后一位,注意是到nlen而不是nlen-1)
        if(j==nlen)return (i-nlen+1);
    }

 画图辅助理解整个过程

 最终代码:

int strStr(char * haystack, char * needle){
    int hlen=strlen(haystack);
    int nlen=strlen(needle);

    if(nlen==0)return 0;
    // 作必要的判断

    // 找到needle不减一的前缀表
    int j=0;
    int *next=(int*)malloc(sizeof(int)*nlen);
    next[0]=j;
    for(int i=1;i<nlen;i++)
    {
        // 当被判断的字符串长度不为1.且前后缀不相同时
        while(j>0&&needle[j]!=needle[i])j=next[j-1];//直至找到相同前后缀,或者字符串 遍历完成

        // 当前后缀相同时
        if(needle[j]==needle[i])j++;//j指针右移一位

        // 把j的值(前缀长度)赋给前缀表中对应的i
        next[i]=j;
    }

    // 用next表做haystack和needle的匹配
    j=0;
    for(int i=0;i<hlen;i++)//注意i此时时用于遍历haystack字符串的指针,从0开始
    {
        //若两个字母不匹配时
        while(j>0&&needle[j]!=haystack[i])j=next[j-1];//j 寻找之前匹配的位置
        
        //若两个字母匹配时
        if(needle[j]==haystack[i])j++;

        //若hay字符串中出现了nee完整的字符串(j遍历到最后一位,注意是到nlen而不是nlen-1)
        if(j==nlen)return (i-nlen+1);
    }
    // 若找不到
    return -1;
}

 注意细节,区分减一不减一,对k的操作差异!KMP算法有点难理解,之后再看看!

时间复杂度O(nlen+hlen)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值