代码随想录09|KMP算法

KMP主要针对场景:在一个串中查找是否出现过另一个串

前缀:包含首字母,不包含尾字母的所有子串

后缀:包含尾字母,不包含首字母的所有子串

在当前对文本串和模式串检索的过程中,若出现了不匹配,利用已经匹配的部分:

在不匹配之前已经完全相同,那么也就意味着 文本串和模式串中的这部分的最长相等前后缀相同,即模式串的前缀和文本串的后缀完全相同,那么就利用前面的最长公共前后缀长度进行跳转,重新匹配。而不是从头匹配。

前缀表(最长相等前后缀为元素的数组):双指针法

一个指向前缀末尾,一个指向后缀末尾,前缀末尾同时也是包括后缀末尾在内往前的字符串的最长相等前后缀。

前缀末尾往复循环匹配,更新后缀指针指向的元素对应的前缀表元素。

1 找出字符串中第一个匹配项的下标

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

2 重复字符串

459. 重复的子字符串

2.1 find

将两个原字符串拼接在一起,掐头去尾之后,如果能找到原字符串,就说明是由重复的字符串所组成

string的find()函数用于找出字母在字符串中的位置。

返回值为目标字符的索引,当没有找到目标字符时返回npos

其他相关用法:

当正向查找与反向查找得到的位置不相同,说明查找的子串不唯一

2.2 KMP

如果一个字符串是由重复子串组成,那么他的最小组成子串就是 字符串除去最长相等前后缀的那一部分

找出最小组成子串的长度,然后用字符串相除,看是否可以整除,可以整除则说明是由重复子串组成。

另外要注意代码22行的第一个条件,必须要有其最长相等前后缀长度不等于0才可以,如果最长相等前后缀为0,那就说明不是由重复子串构成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种高效的字符串匹配法,它通过预处理模式串,构建next数组,来实现在匹配过程中跳过些不必要的比较。下面是KMP算法的C++代码实现[^1]: ```cpp #include <iostream> using namespace std; const int MAXLEN = 255; typedef struct { char ch[MAXLEN]; int length; } SString; void GetNext(SString T, int next[]) { int i = 1, j = 0; next = 0; while (i < T.length) { if (j == 0 || T.ch[i] == T.ch[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } } } int Index_KMP(SString S, SString T, int next[]) { int i = 1, j = 1; while (i <= S.length && j <= T.length) { if (j == 0 || S.ch[i] == T.ch[j]) { ++i; ++j; } else { j = next[j]; } } if (j > T.length) { return i - T.length; } return 0; } int main() { SString S, T; S.length = 10; T.length = 3; strcpy(S.ch, "ababcabcac"); strcpy(T.ch, "abc"); int next[MAXLEN]; GetNext(T, next); int pos = Index_KMP(S, T, next); if (pos != 0) { cout << "匹配成功,位置为:" << pos << endl; } else { cout << "匹配失败" << endl; } return 0; } ``` 以上是KMP算法的C++代码实现。在代码中,我们首先定义了一个结构体SString来表示字符串,包含一个字符数组ch和一个长度length。然后,我们实现了GetNext函数来计算模式串T的next数组,用于在匹配过程中跳过不必要的比较。接着,我们实现了Index_KMP函数来进行KMP算法的匹配过程。最后,在main函数中,我们定义了两个字符串S和T,并调用GetNext函数计算T的next数组,然后调用Index_KMP函数进行匹配,并输出匹配结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值