• Border树(失配树)


    参考资料1
    参考资料2

    前置知识:前缀函数,Border的简单认识

    约定:
    字符串的下标从 \(0\) 开始。\(|s|\) 表示字符串 \(s\) 的长度。
    对于字符串 \(s\),记其每一个字符分别为 \(s_0, s_1, \cdots, s_{|s|-1}\)
    子串 \(s_l, s_{l+1}, \cdots, s_{r-1}, s_r\) 简记为 \(s[l:r]\)。特别地,若 \(l=0\),可记作 \(s[:r]\);若 \(r=|s|-1\),可记作 \(s[l:]\)
    对于字符串 \(a, b\)\(a+b\) 表示拼接操作,即将字符串 \(b\) 拼接到字符串 \(a\) 之后,构成新的字符串。
    记构成的新字符串为 \(c\),则上述拼接操作记为 \(c\gets a+b\)
    其中符号 \(x\gets y\) 表示将 \(y\) 的值赋给 \(x\)
    不论是字符还是字符串,皆不加引号。

    不妨直接来看模板
    我们的目标是快速求出 \(s[:p]\)\(s[:q]\) 的最长公共 \(\text{Border}\) 的长度。

    先来求出每个前缀的所有 \(\text{Border}\)
    显然,长度为 \(i\) 的前缀的所有 \(\text{Border}\) 的长度为 \(\pi(i-1),\pi(\pi(i-1)-1),\cdots\)
    长度为 \(j\) 的前缀的所有 \(\text{Border}\) 的长度为 \(\pi(j-1),\pi(\pi(j-1)-1),\cdots\)
    所以要求出这两个前缀的最长公共 \(\text{Border}\) 的长度,只需要两个指针来从大往小跳,第一次遇到的时候……很自然地就可以使用LCA的技术来进行解决。
    我们只需要对每个长度 \(1\leqslant i \leqslant |s|\) 进行 \(i\Leftrightarrow\pi(i-1)\) 的连边,再以 \(0\) 为根做LCA就可以了。
    需要注意的是如果要求的两个点中其中一个点是另一个点的祖先,答案将为LCA的父亲,因为自己不是自己的 \(\text{Border}\)
    代码没什么好说的。

  • 相关阅读:
    正则表达式和re模块
    面向对象基础
    面向对象高级
    网络编程
    collectiontimeossysjson模块
    继承
    封装
    我在吃饭
    111
    关于羽毛球拍
  • 原文地址:https://www.cnblogs.com/pjykk/p/15857025.html
Copyright © 2020-2023  润新知