• 集训总结DAY.1(18.5.22)——KMP


    DAY 1——5.22

    in the morning 依稀记得我们有一场contest。

    at night

    chf大佬讲KMP,先一波~

    luoguP3375KMP模板题

    KMP算法,又称模式匹配算法,能在线性时间内判定字符串S1[1~N]是否为字符串S2[1~M]的子串。

    一、朴素的做法  O(M*N)

      尝试枚举字符串S2中的每个位置i,把字符串S1与字符串S2的后缀S2[i~M]对齐,向后扫描逐一比较S1[1]与S2[i],S1[2]与S2[i+1]......是否相等。

      

    string s1,s2;
    //s1(n)>=s2(m)
    for(int i=1;i<=n;i++)
    {   
    for(int j=1;j<=m;j++)
    {   
    //字符串下标从0开始     if(s1[i]==s2[j]) ...   }
    }

     

     二、Hash!

    在O(N)的时间内预处理一个字符串的所有前缀Hash值,并在O(1)的时间内查询该字符串任意子串的Hash值。枚举S1中的每个位置i(M<=i<=N),检查字符串S2中的Hash值与字符串A中的子串S1[i-M+1~i]的Hash值是否相同。

     

    那么,什么是KMP?

    1.对字符串S1进行自我匹配,求出一个数组next,其中next[i]表示“S1中以S1结尾的非前缀子串(有i-1个)”与“S1的前缀”能够匹配的最长长度。

    如S1[2~i]与S1[1~i-1],S1[3~i]与S2[1~i-2]......

    由此依次匹配对比,若得出的最大匹配值为k(即为参与比较的字串长度,若匹配,则其长度为匹配值),next[i]=k;  

    next[i]=max{j},其中j<i并且S1[i-j+1~i]=S1[1~j]

    求next数组

    (1)初始化next[1]=j=0,假使next[1~i-1]已求出,求解next[i]。

    (2)不断尝试扩展匹配长度j,如果扩展失败(下一个字符不相等),令j变为next[j],直至j变为0(应该重新从头开始匹配)。

    (3)如果能匹配成功,匹配长度j就增加1.next[i]的值就是j。

     对于next数组,老师在讲课时又提出了几个问题,能加深理解:

    想清楚再看答案哦

    question:next[i]是否能大于next[i-1]+1?  why?

    answer: of course not.因为i表示从1~i的前缀能匹配的最长字符个数。

    next[1]=0;
    for(int i=2,j=0;i<=n;i++)
    {
        while(j>0&&a[i]!=a[j+1]) j=next[j];
        if(a[i]==a[j+1]) j++;
        next[i]=j;
    }    

     

     2.对字符串S1与S2进行匹配,求出一个数组f,其中f[i]表示“S2中以i结尾的子串”与“S1的前缀”能够匹配的最长长度。

    f[i]=max{j},其中j<=i并且S2[i-j+1~i]=S1[1~j]

    (其实求解f和next是很像的,自己写看看)

     

    完整code不再给了,上面的链接点开会有很多很优秀的正解~~

     

    G102的孤儿们都要好好的啊。
  • 相关阅读:
    对于字符串的重复字符的去除
    487-3279
    队列设计(转)
    动态创建JS
    前端技巧:禁止浏览器static files缓存篇(转)
    cas与NGINX整合(转)
    秒杀场景下MySQL的低效(转)
    html禁用缓存
    MD5随机盐值生成法
    SVN There are unfinished transactions detected
  • 原文地址:https://www.cnblogs.com/ve-2021/p/9113312.html
Copyright © 2020-2023  润新知