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与扩展KMP初探

时间: 2024-11-05 00:45:50

KMP与扩展KMP初探的相关文章

KMP与扩展KMP

原文转自:http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.aspx KMP:给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i<lenA),求出A[i]往前和B的前缀匹配的最大匹配长度,记为ex[i](或者说,ex[i]为满足A[i- z+1..i]==B[0..z-1]的最大的z值).KMP的主要目的是求B是不是A的子串,以及若是,B在A中所有出现的位置

KMP和扩展KMP【转】

这种东西基本上在纸上自己推导一下就能做出来XD 转发注明出处 KMP:给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i<lenA),求出A[i]往前和B的前缀匹配的最大匹配长度,记为ex[i](或者说,ex[i]为满足A[i- z+1..i]==B[0..z-1]的最大的z值).KMP的主要目的是求B是不是A的子串,以及若是,B在A中所有出现的位置(当 ex[i]=lenB时).[算法]设next[i]为满足B[i-z

KMP、扩展KMP、Manacher模板

推导过程推荐看这篇: KMP模板: 1 void init(){ 2 int j = nex[0] = -1, i = 0; 3 int len = strlen(str); 4 while(i < len){ 5 if(j == -1 || str[i] == str[j]){ 6 nex[++i] = ++j; 7 }else j = nex[j]; 8 } 9 } 10 int KMP(){ 11 int i = 0, j = 0, sum = 0; 12 int len = strlen

KMP、扩展KMP、MANACHER

一.KMP 作用:用于在一个文本串S内查找一个模式串P出现的位置 string str = "bacbababadababacambabacaddababacasdsd"; string ptr = "ababaca"; 如上图,可得在第10与26处包含ptr数组: 暴力做法:暴力for,碰到不一样的直接返回,从后一个开始继续for,最差能到O(n * m) KMP 做法: 主要的思路是跳,比如你一开始从上面例子里的bacbababadababacambabacad

字符串专题一:KMP与扩展KMP

KMP算法主要用于解决单模式串的匹配问题,即:给定主串s和模式串p,问p是否是s的子串(len(s)<=N, len(p)<=M). 先考虑最朴素的算法,即枚举s中的起点i,检查s[i..i+M-1]是否等于p,这样的时间复杂度为O(NM). 分析一下为什么这样的算法效率低(建议读者手动画个图):设指针i和j分别指向s和p中的字符,不妨假定s[0..k-1]和p[0..k-1]已经匹配上了,而s[k]!=p[k](k<M),这说明s[0..M-1]已经不能匹配上p了,根据朴素算法,指针i

HDU 4333 Revolving Digits 扩展KMP

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来相同,有多少比原来的小. 思路:拓展KMP中的next数组标记的是子串和母串的公共前缀的长度,要将字符串长度变成原来二倍,这样如果变换后不是完全相同的数字也即公共前缀长度大于等于字符串长度,那么字母串公共前缀的下一位的大小比较就是题目所要求的比较.由于相同的数字串只算一次,则只要统计比较第一个"循环节"

扩展KMP复习小记

简介 KMP大家都耳熟能详,扩展KMP只是一个扩展版而已,字面意思啦! 我记得以前打过这个复习小记的,但是不知为何失踪了. KMP与扩展KMP的对比 KMP的next[i]表示从1到i的字符串s,前缀和后缀的最长重叠长度. EXKMP的next[i]表示从1到i的字符串s,和从i到n的字符串st的最长重叠长度. 也就是说KMP是向前的匹配,EXKMP是向后匹配. 扩展KMP问题是KMP问题的补充和加难. 具体内容 重要数组 给定母串S,和子串T.定义n=|S|, m=|T|. extend[i]

【扩展kmp+最小循环节】HDU 4333 Revolving Digits

http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数 [思路] 这个数很大,用字符串处理 比较两个字符串的大小,一位一位很耗时,可以求出最长公共前缀,只比较最长公共前缀后一位 每次将数的最后一位放到最后一位,如abcd变成dabc,cdab,bcda,相当于abcdabcd各个后缀的前四位 这样就变成了求abcdabc

acdream1116 Gao the string!(扩展KMP)

今天是字符串填坑的一天,首先填的第一个坑是扩展KMP.总结一下KMP和扩展KMP的区别. 在这里s是主串,t是模式串. KMP可以求出的是以s[i]为结尾的串和 t前缀匹配的最长的长度.假如这个长度是L的话,则: s[i-L+1...i]=t[0...L] 而所谓的失配指针f[i]指的就是当前i点失配时要匹配的长度,实际是用t文本串去匹配t. 扩展KMP则是以s[i]为起始的串和 t前缀匹配的最长的长度. 假如这个长度的话,则: s[i..i+L-1]=t[0...L] 扩展KMP里的nxt数组