代码随想录算法训练营第九天|KMP算法初步接触 28.实现 strStr() 459.重复的子字符串 字符串总结 双指针回顾

本文介绍了KMP算法的基本概念,如前缀表的构建,以及如何通过next数组实现字符串haystack中快速查找与模式串needle的匹配位置。通过举例和代码展示了算法的核心思想,即遇到不匹配时通过前缀表进行索引跳跃。
摘要由CSDN通过智能技术生成

KMP算法初步了解:

给定一个文本串,一个模式串。假设文本串为aabaabaaf,模式串为aabaaf,KMP算法的作用就是在文本串中找到匹配模式串的字符串。

前缀:模式串中包括首字符,不包括尾字符的任意字符串。

后缀:模式串中包括尾字符,不包括首字符的任意字符串。

最长相等前后缀:对模式串分析,得到前缀表。模式串从一个字符开始,每次增加一位字符,找前后缀相等的数量/最长相等前后缀的长度。

                             a:0;aa:1;aab:0;aaba:1;aabaa:2;aabaaf:0

这样就得到前缀表:010120,涉及到具体实现可以用各种next数组来保存。

那么在KMP算法中,字符串匹配时,发现在aabaab这里匹配不上,即f字符匹配不上,那就找到f前面这个字符的前缀表,是2,那么下次检索就跳转到模式串b(2)的位置开始检索。

这里通俗一点来说,就是发现f匹配不上了,看了一下前缀表,发现f前面两个字符和开头两个字符是一模一样的,那么这里就看看第三个字符一不一样就行。

接下来就是next数组的代码实现:

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

到这里next数组就完成了,接下来就是使用next数组做匹配。

 

int strStr(string haystack, string needle) {
        if (needle.size() == 0) return 0;
        int next[needle.size()];
        getNext(next, needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while (j > 0 && haystack[i] != needle[j]) {
                j = next[j - 1];
            }
            if (haystack[i] == needle[j]) {
                j++;
            }
            if (j == needle.size()) {
                return (i - needle.size() + 1);
            }
        }
        return -1;
    }

整体实现:

class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = j;
        for (int i = 1; i < s.size(); i++) {
            while (j > 0 && s[i] != s[j]) {
                j = next[j - 1];
            }
            if (s[i] == s[j]) {
                j++;
            }
            next[i] = j;
        }
    }
    int strStr(string haystack, string needle) {
        if (needle.size() == 0) return 0;
        int next[needle.size()];
        getNext(next, needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while (j > 0 && haystack[i] != needle[j]) {
                j = next[j - 1];
            }
            if (haystack[i] == needle[j]) {
                j++;
            }
            if (j == needle.size()) {
                return (i - needle.size() + 1);
            }
        }
        return -1;
    }
};

两部分实现中关于遍历的过程其实有很多相似之处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值