kmp匹配

题目传送门

kmp算法

首先我们得先知道朴素版本的字符串匹配的时间复杂度为O(nm),所以我们这时后就得使用复杂度为O(n+m)的kmp算法,我们先看一下算法流程。

我们假设蓝线之前的字符串是已经匹配成功了,但siqj+1却不相等了,那这时候我们就要让红线向后移动,那具体移动多少?这时侯就得运用到kmp算法中的next数组。

1.next数组的求法

首先就是定义,我们知道next它存储的是每一个下标对应的“部分匹配值”,那该怎么求呢?

我们来看以下

nextj ,是p(1,j)串中前缀和后缀相同的最大长度(部分匹配值),即 p(1,next[j])=p(jnextj+1,j)

我们再来模拟一下next数组的求法。

q=abcab

q a b c a b
下标 1 2 3 4 5
next 0 0 0 1 2

next1,前缀为空集,后缀也为空集,则值为0

next2前缀为a,后缀为b,则值为0

next3前缀为a,ab后缀 =c,bc,则值为0

next4前缀 = a,ab,abc后缀 = a,ca,bca值为 1;

next5前缀 a,ab,abc,abca后缀 = b,ab,cab,bcab值为2;

for(int i = 2, j = 0; i <= n; i ++ ) { while(j && q[i] != q[j + 1]) j = ne[j]; if(q[i] == q[j + 1]) j ++ ; ne[i] = j; }

2.匹配字符串

回到开头那个场景,我们这时侯不匹配了,于是我们此时要移动q串(不是移动1格,而是直接移动到下次能匹配的位置,也就是移动nextj)。

由匹配可知 1串等于3串,3串等于2串

for(int i = 1, j = 0; i <= m; i ++ ) { while(j && s[i] != p[j + 1]) j = ne[j];//不能匹配 if(s[i] == p[j + 1]) j ++; if(j == n) { //匹配成功 printf("%d ",i - j); j = ne[j]; } }

for语句第二行表示这时候后面的字符串匹配了,我们就可以将j的为前进一位。

#include<iostream> using namespace std; const int N=100010,M=1000010; char q[N],s[M]; int ne[N];//保存next数组 int main() { int n,m; cin >> n >> q + 1 >> m >> s + 1; for(int i = 2, j = 0; i <= n; i ++ ) { while(j && q[i] != q[j + 1]) j = ne[j]; if(q[i] == q[j + 1]) j ++ ; ne[i] = j; } for(int i = 1, j = 0; i <= m; i ++ ) { while(j && s[i] != q[j + 1]) j = ne[j]; if(s[i] == q[j + 1]) j ++ ; if(j == n) { printf("%d ",i - j); j = ne[j]; } } return 0; }

完整代码。


__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/16497744.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(118)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示