Leetcode刷题笔记 KMP算法

文章详细介绍了KMP算法的原理,并提供了带有详细注释的C++代码实现,用于解决LeetCode上的T28题,即在一个字符串中查找另一个字符串的第一个匹配项的下标。KMP算法的关键在于构造next数组,用于在主串和模式串不匹配时快速调整比较位置。
摘要由CSDN通过智能技术生成

Leetcode刷题笔记 KMP算法

KMP算法代码

Leetcode T28:
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。

自用超详细注释版c++代码

class Solution {
public:
        /*创建一个存储部分匹配值PM的next数组,即next[i]是t[0:i]的最长公共前后缀的长度。
        next数组的意义:
        当主串的某个字符x与模式串的t[i+1]失配时,x应与模式串的子串t[0:i]的最长公共前缀的下一个字符进行比较
        由于字符的下标从0开始,所以最长公共前缀的下一个字符的下标就等于t[0:i]的最长公共前缀的长度。
        总结:
        当主串字符与模式串的t[i]失配时,应改为与模式串的t[next[i-1]]进行比较。
        */
    void creatNext(string t, vector<int> &next){
        //在创建next数组时,可将待求next值的字符,即i指向的字符,视为主串的字符x,将t[0:next[i-1]](即t[0:j],因为next[i++]=++j)视为模式串。
        //定义指针
        int j=0;//j指向前缀末尾,其值等价于最长公共前后缀的长度
        int i=1;//i指向后缀末尾,即next数组待填入数字的位置 
        //初始化next数组
        next[0]=0;
        //更新next数组
        while(i<t.size()){
            //i指向的字符与next[i-1]指向的字符匹配,所以,填写next[i]的值,i和j均自增
            if(t[i]==t[j]){
                next[i++]=++j;
            }
            else{
            //i指向的字符与next[i-1]指向的字符不匹配,所以,根据next表往前遍历寻找能与i指向的字符匹配的位置
                while(j!=0&&t[i]!=t[j]){
                    j=next[j-1];
                }
                if(t[i]==t[j]){
                //找到与i指向的字符匹配的字符
                    next[i++]=++j;
                }
                else{
                //没有公共前后缀,next[i]值为0,i自增j不动
                    next[i++]=0;
                }
            }
        }

    }
    int strStr(string haystack, string needle) {
        vector<int> next(needle.size());
        creatNext(needle,next);
        int j=0;//指向模式串
        int i=0;//指向主串
        for(i=0;i<haystack.size()&&j<needle.size();i++){
            while(j!=0&&haystack[i]!=needle[j]){
                j=next[j-1];
            }
            if(haystack[i]==needle[j]){//字符匹配则i和j同时增大,否则只有i增大
                j++;
            }
        }
        if(j==needle.size())return i-needle.size();//j走完了needle,说明匹配完成
        return -1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值