KMP

KMP

定义

若要在 abcbdbddd中寻找cdb则有

模式串Scdb

目标串Tabcbdbddd

i为目标串指针(i=1开始)

j为模式串指针(j=1开始)

BF(暴力算法)

BF算法是一个普通的暴力匹配算法,其算法思想是先将目标串的第一位与模式串的第一位先进行匹配。若成功,则将匹配模式串与目标串的第二位,若不相等,则将匹配目标串的第二位与模式串的第一位。

模拟一下:

目标串:abeabeabas

模式串:abeabas

(1)(2)abeabeabas(3)abeabas

(4)(5)abbeabeabas(6)abeabas

(7)(8)abeabeabas(9)abeabas

(10)(11)abeabeabas(12)abeabas

(13)(14)abeabeabas(15)abeabas(16)

(17)(18)abeabeabas(19)abeabas

但是睿智的你肯定已经发现了,当我们在匹配失败时,没有必要将i又重新回到1,完全可以将j=3 与其继续比较,这是因为j=6时,S[1,2]=S[4,5],反正到此时已经保证T串的1 ~ j1已经匹配。

由此我们在这里引入border

border

定义:指的是字符串T,在第i位时,T[1,i]中最长的前缀与后缀相同的长度(不包括串本身)。

举例:有T=aba ,则有border[1]=0,border[2]=0,border[3]=1

根据定义可以得到当ST匹配时,在第S[i],T[j]匹配失效时,j可以回到border[j1]+1(j !=1) 继续比较。

举个例子:

S=ababababeT=ababei=5,j=5ij=border[j1]+1=3

但是若border[j1]+1=1 则应当将i++ 以继续比较

接下来便有一个问题,怎么快速求出border

可以观察,假设我们已经求出了border[1i],要求border[i+1],怎么办?

显然我们可以令j=border[i]

S[j+1]=S[i+1]border[i+1]=j+1

反之,则继续上面的步骤,直到有成功的,或者j=0(无满足的前缀与后缀)

并且显然有border[1]=0

所以有以下代码:

char S[maxn];
int border[maxn];
inline void getborder(){
    int j=0;
    border[1]=0;
    for(int i=2;i<=ls;i++){
        while(j&&S[i]!=S[j+1]) j=border[j];
        if(S[i]==S[j+1]) j++;
        border[i]=j;
    }
}

KMP(看毛片)

算法流程:

先计算出border,当然在其他题解里面可能是next

再依次匹配S,T

每次匹配时,j表示S匹配位的上一位,i表示T匹配位的下标。

那么当S[j+1]!=T[i]&&j!=0时,一直取j=border[j]

若有S[j+1]==T[i] ,则j++,i++

反之只有i++

CODE

    j=0;
    for(int i=1;i<=la;i++){
        while(j&&a[i]!=b[j+1]) j=p[j];
        if(a[i]==b[j+1]) j++;
        if(j==lb) write(i-lb+1),j=p[j];
    }

可能算法讲解有些迷糊,主要靠各位大佬们自行多次反复理解。

posted @   轩Demonmaster  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示