找出字符串中第一个匹配的下标(kmp)

kmp最详细的讲解
https://zhuanlan.zhihu.com/p/151421571

题目

给你两个字符串 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 。

思路

暴力解法这里就不说了,重点是看kmp算法,算法的核心是建立next数组(也叫做前缀表),如何建立这个next数组和拿这个数组来匹配是一个重点,相关细节可以看代码随想录的介绍
kmp算法介绍

代码

class Solution {
public:
    //next数组的更新十分神奇,可以好好看看
    vector<int> getNext(string needle) {
        vector<int> next(needle.size(), 0);
        int i= 0;
        int j = 1;
        for(; j < needle.size(); j++) {
            if(needle[j] == needle[i]) {
                i++;
            }else {
                //i要退到两者不相等的位置
                while(i > 0 && needle[i] != needle[j]){
                    i = next[i - 1];
                }
                if(needle[i] == needle[j]) {
                    i++;
                }
            }
            next[j] = i;
        }
        return next;
    }

    int strStr(string haystack, string needle) {
        //使用kmp算法实现的过程,首先是根据needle得出next数组,因为匹配过程要用到这个
        //haystack = "abcabcaba" ,needle = "abcaba"; next = 000121为例
        vector<int> next = getNext(needle);
        int j = 0;
        int i = 0;
        for(; i < haystack.size(); i++) {
            if(haystack[i] == needle[j]) {
                j++;
                //以上的过程一直持续到i = 5, j = 5,那就不等了
            }else {
                //怎么跳转的呢,此时跳的是j = 4,也就是看4是怎么跳的
                while(haystack[i] != needle[j] && j > 0) {
                    j = next[j - 1];
                }
                if(haystack[i] == needle[j]) {
                    j++;
                }
            }
            
            if(j == needle.size()) {
                break;        
            }
        }
        if(j == needle.size()) {
            //说明匹配成功了
            return i - needle.size() + 1;
        }else {
            return -1;
        }
        return -1;
    }
};
posted @ 2023-03-29 13:40  铜锣湾陈昊男  阅读(11)  评论(0)    收藏  举报