KMP与扩展KMP初探

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)