• 傻逼kmp


    最近在打字符串,自然也就打到了kmp

    kmp算法是由D.E. Knuth、J.H.Morris和V.R. Pratt提出的虽然两位都不认识orz

    kmp算法是用来比较字符串是否相同,也就是给定两个字符串,A串和B串,需要回答B串是否为A串字串,我们一般把等待匹配的字符串称之为主串,来匹配的字符串称为模式串

    按照朴素算法来解肯定是很简单的,在A串中不断枚举一个开始节点,若是不匹配就世界退出并更换开始节点,设A,B串长度分别为m,n,这里没有给出代码就是懒

    虽然有最好情况,在开始的时候就能匹配到,时间复杂度为O(n),但也会存在排除最后才能找到的情况,这时算法时间复杂度会退化为O(mn),这就有点难以接受了。。。

    然而kmp算法就比较神奇,可以在O(n)的时间内跑完整个代码,非常稳定

    那么这个算法到底怎么实现呢我也不知道简单来说,就是在A串枚举一个i,B串枚举一个j,看A[i]和B[j]是否匹配,如果匹配,则i和j都往后移一位,如果不匹配,则说明A串从1到i的字串和B串从1到j的字串并不匹配,我们需要在A串的1~i中枚举一个k,使A串的头k个字符和末尾k个字符匹配,使k越大越好(匹配的尽量长),再去跟B串匹配

    其实kmp也可以算是朴素算法的进化版啦

    模拟一遍

    A a b a b a b a c a b a c a b a b a b

    B a b a b a b

    匹配到5时,我们发现了差异,A[5]=a,但是B[5]=b啊!

    朴素算法的思考方式是

    欸欸欸?不匹配?那行我从A串的第2个开始枚举起,那么我再来跑一遍

    kmp的思维方式是

    不匹配?观察A[1]~A[5],我们可以发现字串A[1]~A[3]和A[3]~A[5]是可以匹配的,那么我们将j换为4,i继续推进到6

    知道找到最后我们才能找到答案

    值得一提的是,如果是在不知道怎么读入字符串的同学,可以用cin和char(本蒟蒻就用的cin和charQAQ

    挂个板子题

    https://www.luogu.org/problem/P3375

    emmm贴代码

    #include<bits/stdc++.h>
    using namespace std;
    int nxt[1000010],A,B,j;
    char a[1000010],b[1000010];
    int main(){
        cin>>(a+1)>>(b+1);
        A=strlen(a+1);B=strlen(b+1);
        for (int i=2;i<=B;i++){     
               while(j&&b[i]!=b[j+1])j=nxt[j];    
               if(b[j+1]==b[i])j++;    
            nxt[i]=j;
        }
        j=0;
        for(int i=1;i<=A;i++){
            while (j>0&&b[j+1]!=a[i]) j=nxt[j];
            if (b[j+1]==a[i]) j++;
            if (j==B) {printf("%d
    ",i-B+1);j=nxt[j];}
           }
    
        for (int i=1;i<=B;i++)
            printf("%d ",nxt[i]);
        return 0;
    }
  • 相关阅读:
    一个好用的web甘特图
    应用ExcelPackage导出Excel
    Base64中文不能加密问题
    Sql Server存储过程和函数浅谈
    .NET反编译之Reflector基础示例
    NPOI导出数据到Excel
    twitter接口开发
    Nginx基本属性配置详解
    ssh-keygen创建证书
    asp.net core 设置默认文档index.html
  • 原文地址:https://www.cnblogs.com/XYH-xyh/p/11277228.html
Copyright © 2020-2023  润新知