KMP
KMP算法主要用于字符串匹配中的单串匹配
next函数:表示当前字符失配时,应从模式串的第几位开始匹配(越大越好)。即模式串的前缀与以t[i]为结尾的后缀的最长相同部分的长度。
代码如下(pascal)
var s,t:string; next,ans:array[0..100] of longint; i,j:longint; begin readln(s); readln(t); next[1]:=0; {构造next} j:=0; for i:=2 to length(t) do begin while (j>0)and(t[j+1]<>t[i]) do j:=next[j]; {失配} if t[j+1]=t[i] then j:=j+1; next[i]:=j; end; {KMP主程序} j:=0; for i:=1 to length(s) do begin while (j>0)and(t[j+1]<>s[i]) do j:=next[j]; {失配} if t[j+1]=s[i] then j:=j+1; if j=length(t) then {找到匹配} begin inc(ans[0]); ans[ans[0]]:=i-length(t)+1; j:=next[j]; end; end; for i:=0 to ans[0] do writeln(ans[i]); end.
扩展KMP
顾名思义就是KMP算法的扩展,其可以求出以s[i]为开始的字符串,与t的最长公共前缀。
扩展KMP的next函数:表示以t[i]为开始的字符串,与t的最长公共前缀的长度。
扩展KMP的extend函数:表示以s[i]为开始的字符串,与t的最长公共前缀的长度。
代码如下(pascal)
var s,t:ansistring; i,j,k,p,l,n,m:longint; next,extened:array[0..1000] of longint; begin readln(s); readln(t); n:=length(s); m:=length(t); s:=s+‘@‘; {防越界} t:=t+‘#‘; {防越界} {构造next} j:=0; while T[1+j]=T[2+j] do inc(j); next[2]:=j; k:=2; for i:=3 to m do begin p:=k+next[k]-1; {p为最远的已比较过的点} l:=next[i-k+1]; {l为t与t[i-k+1..m]的LCP} if l+i-1<p then next[i]:=l else begin if p-i+1>0 then j:=p-i+1 else j:=0; while T[i+j]=T[1+j] do inc(j); next[i]:=j; k:=i; {更新k} end; end; {Extened_KMP主程序} j:=0; while T[1+j]=S[1+j] do inc(j); extened[1]:=j; k:=1; for i:=2 to n do begin p:=k+extened[k]-1; {p为最远的已比较过的点} l:=next[i-k+1]; {l为t与t[i-k+1..m]的LCP} if l+i-1<p then extened[i]:=l else begin if p-i+1>0 then j:=p-i+1 else j:=0; while S[i+j]=T[1+j] do inc(j); extened[i]:=j; k:=i; {更新k} end; end; for i:=1 to n do writeln(extened[i]); end.
KMP与扩展KMP初探
时间: 2024-11-05 00:45:50