赞
踩
知识点
KMP(Knuth-Morris-Pratt)算法是一种用于字符串匹配的高效算法。其原理基于字符串匹配时的特性,通过预处理模式字符串(待匹配字符串)的信息,避免在匹配过程中重复比较已经匹配过的部分。
前缀表记录了模式字符串中最长相同前后缀的长度
前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串。
后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。
最长相同前后缀的长度:
举一个例子“ABABBABC”
A -> 0
AB -> 0
ABA -> 1
ABAB -> 2
ABABB -> 0
ABABBA->0
ABABBAB->2
ABABBABC->0
再举个栗子“aabaaf”
a->0
aa->1
aab->0
aaba->1
aabaa->2
aabaaf->0
next 数组 其实就是前缀表的不同表现形式,主流的写法有三种:
拿“aabaaf”来说,需要找到aabaabaaf的匹配下标
第一种next数组表示方式为[0, 1, 0, 1, 2, 0], 当他遍历到f的时候发现f和b有冲突,那么找到f对应的前缀表位置的前一位的值为2,那么之前回退到前缀表下标为2的地方。
第二种next数组表示方式为[-1, 0, 1, 0, 1, 2],当他遍历到f的时候发现f和b有冲突,那么找到f对应的前缀表位置的值为2,那么之前回退到前缀表下标为2的地方。
第三种next数组表示方式为[-1, 0, -1, 0, 1, -1],当他遍历到f的时候发现f和b有冲突,那么找到f对应的前缀表位置的前一位的值为1,加1之后,那么之前回退到前缀表下标为2的地方。
难点:next 数组怎么写
我们就看第一种 next 数组的写法
初始化
前后缀不相等的情况
前后缀相等的情况
更新 next 数组
/* i:表示后缀末尾;j表示前缀末尾(也表示冲突返回的下标位置)*/ // 初始化 int j = 0; next[0] = 0; for(int i = 1; i < s.size(); i++){ // 前后缀不相等的情况, 根据不变性原理,j也需要回退到j对应的前一位的值对应的下标值的位置 while(j > 0 && s[i] != s[j]){ j = next[j - 1]; } // 前后缀相等的情况 if(s[i] == s[j]){ // 更新next数组 next[i] = j++; } }
题目
给你两个字符串 haystack
和 needle
,请你在 haystack
字符串中找出 needle
字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle
不是 haystack
的一部分,则返回 -1
。
28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)
题解1:暴力解法
- class Solution {
- public:
- int strStr(string haystack, string needle) {
- for (int i = 0; i + needle.size() <= haystack.size(); i++) {//i + needle.size() <= haystack.size()
- if (haystack[i] == needle[0]) {
- bool flag = true;
- int j = needle.size() - 1;
- for (; j >= 0; j--) {
- if (haystack[i + j] != needle[j])
- {
- flag = false;
- break;
- }
- }
- if(flag ){ // 善用flag
- return i;
- }
- }
- }
- return -1;
- }
- };
题解2:KMP解法
- class Solution {
- public:
- void getNext(int* next, const string& s){
- int j = 0;
- next[0] = 0;
- 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;
- }
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。