首页 > 其他分享 >KMP与Lca应用——最长公共border

KMP与Lca应用——最长公共border

时间:2024-11-25 22:14:21浏览次数:6  
标签:前缀 int KMP Lca 字符串 border 最长

问题提出

给定你一个字符串,有\(n\) 次询问,每次给出两个数\(a\),\(b\),希望求出该字符串以\(a\),\(b\)下标结尾的两段前缀的最长公共\(border\)。(一个字符串的\(border\)同时为其后缀与前缀)

初步分析

首先我们需要考虑一个字符串的最长\(border\)求法,毕竟需要求的是两字符串的最长公共\(border\)。从\(border\)的定义下手,我们可以发现我们需要将该字符串的后缀与其前缀进行匹配,所以考虑其与字符串匹配的关系。

再仔细分析,我们发现待求\(border\)字符串是给定字符串的一段前缀,所以其最长\(border\)一定也是给定字符串的一段前缀,且该\(border\)处于前面的结束位置是最后一个点在进行字符串匹配时的最后一个失配位置,(因为\(border\)应是一段后缀,其结尾必定是待求字符串的结尾)。

经过上述分析,我们很自然的会想到\(KMP\)算法中的\(fail\)数组,它正好记录了给定字符串中每一个字母的最后一个失配位置,(不会\(KMP\)的请戳这里),这部分代码如下:

for(int i = 2 , j = 0 ; i <= len ; ++i)	//这里字符串下标默认从1开始
{
    while(str[i] != str[j + 1] && j != 0)
        j = fail[j] ;
    if(str[i] == str[j + 1])
        ++j , fail[i] = j ;
}

进入正题

知道一段前缀的最长\(border\)怎么求后,我们再考虑如何求出两段前缀的最长公共\(border\)。

考虑一段字符串的\(border\)的形式,我们会发现其实每一次向前跳的过程都是相当于在向其父节点跳跃,形成一个树形的结构,形式化地再来解释两段前缀的最长公共\(border\)的前缀的结尾点就是它们在这个\(fail\)树上的最近公共祖先表示的点,于是我们考虑在进行\(KMP\)匹配是顺便将这棵\(fail\)树建出,(我们此处采用倍增\(lca\)写法)(不会\(lca\)的请戳这里),代码如下:

\(KMP\)+建树部分:

for(int i = 2 , j = 0 ; i <= len ; ++i)
{
    while(str[i] != str[j + 1] && j != 0)
        j = fail[j] ;
    if(str[i] == str[j + 1])
        ++j , fail[i] = j , dep[i] = dep[j] + 1 ;
    else
        fail[i] = 0 , dep[i] = 0 ;
    fa[i][0] = fail[i] ;
    for(int k = 1 ; k <= 20 ; ++k)
        fa[i][k] = fa[fa[i][k - 1]][k - 1] ;
}

倍增\(lca\)部分:

int lca(int u , int v)
{
    int temp = 0 ;
    if(dep[u] < dep[v])
        swap(u , v) ;
    temp = dep[u] - dep[v] ;
    for(int i = 0 ; (1 << i) <= temp ; ++i)
        if((1 << i) & temp)
            u = fa[u][i] ;
    if(u == v)
		return 0 ;
    for(int i  = 20 ; i >= 0 ; --i)
        if(fa[u][i] != fa[v][i])
            u = fa[u][i] , v=fa[v][i] ;
    return fa[u][0] ;
}

完结撒花!!!

标签:前缀,int,KMP,Lca,字符串,border,最长
From: https://www.cnblogs.com/Torrentolf/p/18568897

相关文章

  • Z函数(扩展KMP)
    扩展KMP(Z函数)Z数组简单理解\(Z[i]\)表示字符串从i出发,与整体相比有多长的公共前缀aaabaac7210210可以先理解马拉车再来看首先,设置两个类似的东西,关键点\(c\)和最右边界\(r\),表示\(Z[c]\)是目前所有\(Z\)中,\(i+Z[i]\)最右边的那个对于: r01......
  • 对KMP算法的疑问与理解
    对KMP算法的疑问与理解核心:在逐字符遍历主串与模式串的过程中,发生失配时,不回溯主串的i字符指针,而是通过确定已经匹配过的模式串的子串的前缀集合与后缀集合的交集中最长元素的长度,来移动模式串的j字符指针,实现模式串的整体向右滑动,跳过绝不可能发生的字符串匹配,以此实现......
  • 【算法】C++KMP算法的简洁实现
    目录简介next数组匹配完整代码简介对于朴素的字符串匹配算法,如果想在主串中寻找到第一次出现子串的位置,需要依次枚举主串中的每一个位置作为起始位置进行匹配尝试,如果主串中存在许多与子串相似结构的部分,那么朴素算法会进行大量的无用枚举,时间复杂度非常之高。KMP算法......
  • 【Unity】CinemachineVirtualCamera:实现第一人称视角控制
    相机视角的控制,利用CinemachineVirtualCamera插件(在packageManager中下载)实现键盘和鼠标控制第一人称视角。WASD前进后退向左向右,QE左右旋转;鼠标滚轮控制远近、俯仰和升降。另外还支持鼠标靠近边缘移动、鼠标拖拽等控制方式。成果展示Scene部分主相机增加CinemachineBrain组......
  • 树上差分+lca 黑暗的锁链
    //**太久不写了,感觉很难受。。。比赛最近打得也不好,课内任务又重,还要忙着做项目。何去何从。今天又写了一题,用了树上差分的知识。下面来整理整理。1.首先让我们学一下lca(最小公共父节点) 我用的是倍增来求的。总共其实就是两步:dfs打ST表预处理每个点的上面节点 lca求两......
  • KMP算法的实现
             这是C++算法基础-数据结构专栏的第二十六篇文章,专栏详情请见此处。引入     KMP算法是一种可以快速查找某一字符串在一个文本中的所有出现的算法。        下面我们就来讲KMP算法的实现。定义        Knuth–Morris–Pratt算......
  • 【学术会议:中国杭州,机器学习和计算机应用面临的新的挑战问题和研究方向】第五届机器学
    您的学术研究值得被更多人看到!在这里,我为您提供精准的会议推荐,包括水利土木工程、计算机科学、地球科学、机械自动化、材料与制造技术、经管金融、人文社科等主流学科相关领域的国际会议。快速的稿件录用和高效的检索服务将确保您的研究成果迅速传播。关注我,寻找与您研究......
  • [学习笔记]树链剖分(简易版) 及其LCA
    树链剖分先讲解一下一些基础定义(都是在树上)重儿子:一个节点中所有儿子中子树大小最大的一个儿子(每个节点最多有一个重儿子)轻儿子:一个节点除重儿子外所有的节点重链:若干个重儿子组成的链链顶:一条链中深度最小的节点以下图为例子(红色连续线段为重链)对于节......
  • PERIOD - Period(kmp求border)
    #include<bits/stdc++.h>usingnamespacestd;#definexfirst#defineysecondtypedefpair<int,int>PII;typedeflonglongll;typedefunsignedlonglongull;typedefunsignedintuint;typedefvector<string>VS;typedefvector<int>......
  • 从kmp到AC自动机
    知道kmp的请跳过这一段找到最清晰的解析kmp我看了约114514个解析才搞懂如何求next首先,next[i]本应表示0~i的字符串的最长相同前缀后缀的长度。不过为了方便匹配,实际可以存最长相同前缀后缀时前缀最后一个的地址听起来好绕那这么说吧:例如串abaabaabaabnext[0]=-1肯定找......