KMP算法

KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。

问题求a字符串与b字符串中子串相同的串首位置。

暴力就不说了,设a长m,b长n,每次枚举比对每个字符,复杂度O(nm)。

KMP主要思想:如果一个字符串的子串与前缀相等,那么在查找时就可以直接将前缀跳至该子串的位置。复杂度O(n)。

nxt[x]记录x位置字符在查询串中的跳转位置。

eg:对于串abaabacac:

 a b a a b a c a c

-1 0 0 1 1 2 3 0 1

复制代码
inline void getnxt()
{
    int j=0,k=-1;
    nxt[0]=-1;
    while(j<s.length()-1)
    {
        if(k==-1||s[j]==s[k])nxt[++j]=++k;
        else k=nxt[k];
    }
}
复制代码

查询时跳转即可。

模拟一下就知道啦~

全代码:

复制代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
string s,t;
int nxt[1000];
inline void getnxt()
{
    int j=0,k=-1;
    nxt[0]=-1;
    while(j<s.length()-1)
    {
        if(k==-1||s[j]==s[k])nxt[++j]=++k;
        else k=nxt[k];
    }
}
inline int indexkmp()
{
    int i=0,j=0;
    while(i<s.length() and j<t.length())//如果比完了就退出来了 
        if(i==-1 or s[i]==t[j])i++,j++;
        else i=nxt[i];
    if(i>=s.length())return j-s.length();
    return -1;
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>s>>t;
    getnxt();
    cout<<indexkmp()+1;
    return 0;
}
复制代码

 例题

洛谷P3375

复制代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=1e6+5;
int nxt[maxn];
char a[maxn],b[maxn];
int lena,lenb;
inline void getnxt()
{
    int k=-1,j=0;
    nxt[0]=-1;
    while(j<lena)
        if(k==-1 or a[k]==a[j])
        nxt[++j]=++k;
        else k=nxt[k];
}
inline void indexkmp()
{
    int j=0,i=0;
    while(j<lena and i<lenb)
        if(j==-1 or a[j]==b[i]){
            i++,j++;
            if(j==lena){
                printf("%d\n",i-lena+1);
                j=nxt[j];
            }
        }
        else j=nxt[j];
}
int main()
{
    scanf("%s\n%s",&b,&a);
    lena=strlen(a);
    lenb=strlen(b);
    getnxt();
    indexkmp();
    for(int i=1;i<=lena;i++)
    printf("%d ",nxt[i]);
    return 0;
}
复制代码

 

posted @   Star_Cried  阅读(141)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示