浅谈KMP
来源:互联网 发布:java concurrent书籍 编辑:程序博客网 时间:2024/06/06 00:39
KMP
前言:
由于本人能力有限,很多步骤都是按照抽象思维理解,并没有像很多其它讲解KMP的算法,是借助了图加深理解的,请见谅.
基本知识:
①
②最基本的
③
算法讲解:
问题:
给定两个字符串
问
朴素的想法:
枚举指针
当
那么KMP 是如何做的呢?
我们用两个指针
意思就是:
那么现在假设需要检验
当
而当
当
现在我们看一看当
这时
为什么要找到这样一个
其实这是
接下来我会详细分析一下为什么要找到这样的一个
假设我们找到这样一个最大的
而我们知道
(这里不仅是核心,更是
当找到这样一个
显然
那么可能有人问了?如何一直缩小,怎么缩小?我们继续往下细想.
好,
现在有一个问题,如何每次对于一个
因为每次求一个
显然这是可以做到的.
因为只要你明白了
我们现在假设
因为现在我只有一个串,所以进行的,是这样的一个“自我匹配”的过程.
那么我也可以设一个值
对于
当
当
为什么可以直接把
如图,当
且在串
而
其实这个步骤是与上述匹配时的过程是一样的,只不过这个是进行“自我匹配”.
对于
代码部分:
var p:array[0..100] of longint; s1,s2:string; n,i,j,tot:longint;begin readln(s1); readln(s2); p[1]:=0; j:=0; for i:=2 to length(s2) do begin while (s2[j+1]<>s2[i]) and (j>0) do j:=p[j]; if s2[j+1]=s2[i] then inc(j); p[i]:=j; end; //自我匹配 j:=0; for i:=1 to length(s1) do begin while (s2[j+1]<>s1[i]) and (j>0) do j:=p[j]; if s2[j+1]=s1[i] then inc(j); if j=length(s2) then begin inc(tot); //统计个数 j:=p[j]; //这里一样运用到了KMP的核心思想,这么操作可以方便继续往下找其他可能被匹配的串 end; end; //KMP匹配 if tot>0 then begin writeln('YES'); writeln(tot); end else writeln('NO');end.
让我们看一道简单的例题:
https://jzoj.net/senior/#main/show/1536
题意:
给定一个字符串,求其中同时满足前缀串、后缀串相等的所有字符串.
如abcabc ,则′abc′ 为一个同时满足前缀后缀相等的字符串.
题解:
很显然,我们既然要找同时满足前缀后缀相等,那么我对于一个字符串,我求出其顺序对应的
代码:
var p,ans:array[0..400000] of longint; i,j,tot:longint; s:ansistring;procedure dfs(x:longint);begin if p[x]>0 then begin inc(tot); ans[tot]:=p[x]; dfs(p[x]); end;end;begin readln(s); j:=0; for i:=2 to length(s) do begin while (s[i]<>s[j+1]) and (j>0) do j:=p[j]; if s[j+1]=s[i] then inc(j); p[i]:=j; end; dfs(length(s)); for i:=tot downto 1 do write(ans[i],' '); write(length(s),' ');end.
再看一道利用
https://jzoj.net/senior/#main/show/4886
题意:
求任意构造的小写字符串且不包含给定串的串的个数.
我们可以设
显然,当给定串无重复字母时,我们可以这么考虑转移状态:
当下一位选给定串的第
当下一位选给定串的第
当下一位选给定串的其它位时,因为无重复字母,故不匹配,故更新到
但是,如果有重复字母呢?
如:
设
那么显然,这里的
那么如果有这么一个匹配数组,下次我就可以用
所以,问题转化为如何求
显然,一种暴力的求法:
ss:=s;fillchar(a,sizeof(a),0);for i:=0 to length(s)-1 do for ch:='a' to 'z' do begin s:=ss; s[i+1]:=ch; flag:=false; for j:=1 to i+1 do if copy(s,j,i+2-j)=copy(ss,1,i+2-j) then begin flag:=true; break; end; if flag then a[i,ch]:=i+2-j; end;
事实上,我们可以借鉴
j:=0;fillchar(next,sizeof(next),0);fillchar(a,sizeof(a),0);for i:=2 to length(s) dobegin while (j>0) and (s[j+1]<>s[i]) do j:=next[j]; if s[j+1]=s[i] then inc(j); next[i]:=j;end;for i:=0 to length(s) do for ch:='a' to 'z' do begin j:=i; while (j>0) and (s[j+1]<>ch) do j:=next[j]; if s[j+1]=ch then inc(j); a[i,ch]:=j; end;
- 浅谈KMP
- kmp算法浅谈
- 浅谈KMP算法
- 浅谈KMP算法
- 浅谈kmp算法
- 浅谈KMP算法
- 浅谈扩展KMP算法
- 浅谈扩展KMP
- 浅谈KMP算法
- 浅谈KMP(易理解)
- 浅谈KMP算法的延伸
- 浅谈KMP算法及实现
- 浅谈字符串匹配的KMP算法
- 浅谈KMP“串”的模式匹配问题
- 浅谈字符串匹配算法—BF算法及KMP算法
- 浅谈Manacher算法与扩展KMP之间的联系
- 浅谈字符串匹配算法—BF算法及KMP算法
- HDU 4333 浅谈扩展KMP 线性求NXT数组模板
- 释放动态数组
- Mysql error 1452
- shell编程其实真的很简单(五)
- Python练手项目0015
- java 基础知识
- 浅谈KMP
- Python -- 5. 用户输入和while 循环
- 4475: [Jsoi2015]子集选取
- ps 与 top 对于cpu使用率不一致的问题
- NZT基本介绍
- 使用jaxp对XML文件进行dom解析
- win32api之添加水印
- AfxBeginThread如何安全退出
- [LeetCode]135. Candy