首页 > 其他分享 >KMP

KMP

时间:2022-09-29 22:34:57浏览次数:43  
标签:势能 周期 next Prefix KMP 字符串 Border

Border

如果字符串 \(S\) 的同长度的前缀和后缀完全相同,即 \(Prefix[i] = Suffix[i]\)
则称此前缀(后缀)为一个 \(Border\)(根据语境,有时 \(Border\) 也指长度)。

特殊地,字符串本身也可以是它的 \(Border\),具体是不是根据语境判断。

周期和循环节

对于字符串 \(S\) 和正整数 \(p\),如果有 \(S[i] = S[i − p]\),对于 \(p < i ≤ |S|\) 成
立,则称 \(p\) 为字符串 \(S\) 的一个周期。
特殊地,\(p = |S|\) 一定是 \(S\) 的周期

若字符串 \(S\) 的周期 \(p\) 满足 \(p \:\: |\:\: |S|\),则称 \(p\) 为 \(S\) 的一个循环节
特殊地,\(p = |S|\) 一定是 \(S\) 的循环节

重要性质

Border vs 周期

\(p\) 是 \(S\) 的周期 ⇔ \(|S| − p\) 是 \(S\) 的 \(Border\)

证明

\(p 为 S 的周期 ⇔ S[i − p] = S[i]\)
\(q 为 S 的 Border ⇔ S[1, q] = S[|S| − q + 1, |S|] ⇔ S[1] = S[|S| − q + 1], S[2] = S[|S| − q + 2], . . . , S[q] = S[|S|]\)
\(所以|S|-q是一个周期\)
\(易得:p + q = |S|\)

因此,字符串的周期性质等价于 \(Border\) 的性质,
求周期也等价于求 \(Border\)。

警告:\(Border\) 不具有二分性。

Border 的传递性

\(S\) 的 \(Border\) 的 \(Border\) 也是 \(S\) 的 \(Border\)

求 \(S\) 的所有 \(Border\) 等价于求所有前缀的最大 \(Border\)

KMP

next数组

\(next[i]=Preffix[i]\)的非平凡(去掉字符串本身)的最大\(Border\)
\(next[1]=0\)

考虑 \(Prefix[i]\) 的所有(长度大于 \(1\) 的)\(Border\),去掉最后一个字母,就
会变成 \(Prefix[i − 1]\) 的 \(Border\)。

因此求 \(next[i]\) 的时候,可以遍历 \(Prefix[i − 1]\) 的所有 \(Border\),即
\(next[i − 1], next[next[i − 1]], . . . , 0,\)检查后一个字符是否等于 \(S[i]\)。

复杂度分析

\(考虑使用势能分析进行讨论:\)
\(如果 next[i] = next[i − 1] + 1,则势能会增加 1\)
\(否则势能会先减少到某个 next[j],然后有 next[i] = next[j] + 1,势能 也会增加 1,在寻找 next[j] 的过程中,势能会减少,每次至少减少 1。\)
\(还有一种情况,next[i] = 0,势能清空,且不会增加。\)
\(综上,势能总量为 O(N),因此整体的复杂度也是 O(N),常数为 2 左右 (很小)。空间复杂度也为 O(N)。\)

实现

void init(string s){
    //s="!"+s' 使得s从[1,len] 
    len=s.length()-1;
    t=s;
    for(int i=2;i<=len;i++){
        nxt[i]=nxt[i-1];
        while(nxt[i] && s[i]!=s[nxt[i]+1])nxt[i]=nxt[nxt[i]];
        nxt[i]+=(s[i]==s[nxt[i]+1]);
    }	
    return ;
}

标签:势能,周期,next,Prefix,KMP,字符串,Border
From: https://www.cnblogs.com/hh--boke/p/16743333.html

相关文章

  • Leetcode 字符串轮转 KMP
    解题思路题面两倍s1变成字符串匹配,用KMP。KMP预先处理模式串(短串)的\(next[]\)数组,\(next[]\)的意思为自我匹配一样的值的下一个的位置。复杂度\(O(n)\)代码classSo......
  • 暴力匹配算法、KMP算法
    应用实例暴力匹配算法代码实现publicclassViolenceMatch{ publicstaticvoidmain(String[]args){ //测试暴力匹配算法 Stringstr1="硅硅谷......
  • CF494B Obsessive String KMP+前缀和优化DP
    给一份看起来字数比较少的题解?题意给一个字符串\(s\),和一个字符串\(t\)。在\(s\)中取出任意多个不重叠的子串(可以有子串没有被取出),使得每个子串都包含\(t\),求方案......
  • KMP算法,BF算法
    串、BF算法、KMP算法概述需要掌握:1、串的相关概念,串与线性表之间的异同2、顺序串,和链串中串的基本的基本运算算法设计3、模式匹配算法BF、和KMP算法串......
  • KMP 算法实现
    #coding=utf-8defget_next_list(findding_str):#求一个字符串序列每个位置的最长相等前、后缀j=0#最长相等前缀的末位next=[0]#next数组用......
  • KMP算法
    朴素的模式匹配算法朴素算法就是以主串的每一个字符作为子串的开头,与要匹配的字符串(称为模式串)进行匹配,匹配失败则主串退回到这次匹配首位的下一位,重新进行匹配。主......
  • 【学习笔记】KMP字符串匹配
    字符串匹配——KMP算法给定两个字符串s1和s2,询问s2在s1中出现的位置(定义为出现时的第一个字符在s1中的位置)暴力枚举看到字符串匹配(如果你还不会KMP/Hash的话),八成是......
  • kmp+st表
    前言  时隔两年再一次登上账号  本菜鸡尝试回归捏   复习了kmp和st表发现自己没有发过博客代码#include<iostream>#include<cstring>usingnamespaces......
  • KMP&Z函数详解
    KMP一些简单的定义:真前缀:不是整个字符串的前缀真后缀:不是整个字符串的后缀当然不可能这么简单的,来个重要的定义前缀函数:给定一个长度为\(n\)的字符串\(s\),其\(前......
  • KMP算法的底层理解
    KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。KMP的精髓所在就是前缀表。(下面用next[]数组来表......