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

力扣原题链接

一、题目描述

二、思路

使用KMP算法去解决,关于KMP算法以及前缀表的具体内容:帮你把KMP算法学个通透!

关于计算 needle 字符串的前缀表(数值什么的与动图稍有不同,但思路相同)

  1. 首先令 j = 0,i = 1,且next [ 0 ] = 0;
  2. 开始进入循环比较 needle [ j ] 与 needle [ i ] :
  3. 若二者不同,令 j 倒退成 next [ j - 1 ],即 j = next [ j - 1 ],并再次比较,直至找到相同的字符或者 j > 0 为止;(为啥是倒退回next [ j - 1 ] 嘞?因为当 s[ j ] 的前一个元素的 next 数组的值不为零时,则前边有与它相等的前缀,那么倒退回 j = next [ j - 1 ] ,即指向上一组最长相等前后缀中前缀的后一个元素去判断是否与此时的 s [ i ] 相等)
  4. 若二者相同时,j++;
  5. 最后将 j 赋值给 next [ i ] 后继续循环;

关于比较 haystack 与 needle,判断 haystack 字符串中是否包含 needle 字符串(数值什么的与动图稍有不同,但思路相同):

  1. 初始化 i = 0, j = 0;
  2. 先判断 needle 是否为空字符串,是则直接输出 0;(不知道为啥,但是说是说这与C语言的 strstr() 以及 Java的 indexOf() 定义相符)
  3. 开始比较 haystack[ i ] 和 needle[ j ]:
  4. 当 haystack[ i ] != needle[ j ] 并且 j > 0 时,将 j 跳到 next [ j - 1 ],即 j = next [ j - 1 ];(为啥跳到 next [ j - 1 ] 嘞?因为若next [ j - 1 ] != 0 时,则代表此时的 haystack [ i ] 前 next [ j - 1 ] 个元素与 needle 字符串前 next [ j - 1 ] 相同,直接去比较后面的就成)
  5. 当 haystack[ i ] == needle[ j ],继续循环直至 i 等于 haystack 的长度或 j 等于 needle 的长度为止;
  6. 若 j 等于 needle 的长度,则输出 i - j;反之则输出 -1;

三、解题过程

  • 实现计算 needle 字符串前缀表接口函数

void getNext(char* s, int* next, int sLen){
    int j = 0, i = 1;
    next[j] = 0;
    for(; i < sLen; i++){
        while(j - 1 >= 0 && s[j] != s[i]){
            j = next[j - 1];
        }
        if(s[j] == s[i]) j++;
        next[i] = j;
    }
}
  • 找出字符串中第一个匹配项的下标

int strStr(char * haystack, char * needle){
    int i = 0, j = 0;
    int hLen = strlen(haystack);
    int nLen = strlen(needle);
    if(nLen == 0) return 0;
    int* next = (int*)malloc(sizeof(int) * nLen);
    getNext(needle, next, nLen);
    for(; i < hLen && j < nLen; i++){
        while(j > 0 && haystack[i] != needle[j]){
            j = next[j - 1];
        }
        if(haystack[i] == needle[j]) j++;
    }
    if(j == nLen) return i - j;
    return -1;
}

四、代码

void getNext(char* s, int* next, int sLen){
    int j = 0, i = 1;
    next[j] = 0;
    for(; i < sLen; i++){
        while(j - 1 >= 0 && s[j] != s[i]){
            j = next[j - 1];
        }
        if(s[j] == s[i]) j++;
        next[i] = j;
    }
}

int strStr(char * haystack, char * needle){
    int i = 0, j = 0;
    int hLen = strlen(haystack);
    int nLen = strlen(needle);
    if(nLen == 0) return 0;
    int* next = (int*)malloc(sizeof(int) * nLen);
    getNext(needle, next, nLen);
    for(; i < hLen && j < nLen; i++){
        while(j > 0 && haystack[i] != needle[j]){
            j = next[j - 1];
        }
        if(haystack[i] == needle[j]) j++;
    }
    if(j == nLen) return i - j;
    return -1;
}

时间复杂度:O(m*n),空间复杂度:O(n)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值