首页 > 其他分享 >忘光了,所以复习【STR】

忘光了,所以复习【STR】

时间:2023-03-07 15:57:30浏览次数:53  
标签:忘光 复习 后缀 texttt link endpos STR operatorname mathrm

字符串

本文字符串下标从 \(1\) 开始。

\(S[l,r]\) 表示字符串 \(S\) 从 \(l\) 到 \(r\) 的部分。

速通

哈希

没什么可说的,我也不喜欢用。

trie

顾名思义,就是一个像字典一样的树。

基础

不多说了。

01trie

在一些题目中,可以用 trie 维护 01 串。

最长异或路径

给定一棵 \(n\) 个点的带权树,求异或和最大的简单路径。

\(0\le n\le 10^5,0\le w<2^{31}\)。

solution

考虑树上两点路径的异或和可以转化为根到两点的异或和异或起来。

于是转化为求寻找两点使两点的权值的异或和最大。

用 trie 维护:不断插入一个数,查询这个数与已插入的数的最大异或和是多少(只要尽量保证前缀是 1)。

自动机

定义

自动机是一个对信号序列进行判定的数学模型。

比如说,你在初始状态,可以往几条路走,通过这几条路可以走到其他状态。

一个确定有限状态自动机(DFA,deterministic finite automation)由以下五部分构成:

(另外有个东西叫做 NFA,以后可能会提到)

  • 字符集(\(\sum\)),该自动机只能输入这些字符。
  • 状态集合(\(Q\)),顾名思义。
  • 起始状态(\(st\)),同样顾名思义,\(st\in Q\)。
  • 接受状态集合(\(F\)),\(F\subseteq Q\),或终止状态集合。
  • 转移函数(\(\delta(x,y)\)),\(x\) 是一个状态,\(y\) 是字符串,意思就是从 \(x\) 开始,走一个字符串 \(y\) 。

以上的字符串均为广义的。

想要更快的理解,可以把 DFA 看做一个有向图,但是 DFA 只是一个数学模型。

另外不难发现 trie 也是自动机,我称其为广义前缀自动机。下面就拿 01trie 举个例子。

v51RDP.png

  • \(\sum\):0/1。
  • \(Q\):每个节点。
  • \(st\):如图。
  • \(F\):如图黄点。
  • \(\delta\):\(\delta(st,101)\)。

边可以看做状态转移。

序列自动机

对于字符串 \(S\) 的一个子串 \(s\),\(\delta(st,s)\) 表示 \(s\) 在 \(S\) 中第一次出现时末位。

转移(\(u\) 是位置,\(c\) 是个字符):\(\delta(u,c)=\min(i|i>u,s_i=c)\)

可以通过记录下一个字符出现位置来实现。

给你两个由小写英文字母组成的串 \(A\) 和 \(B\),求:

  • \(A\) 的一个最短的子串,它不是 \(B\) 的子序列。
  • \(A\) 的一个最短的子序列,它不是 \(B\) 的子序列。

\(n\le2000\)

solution

第一个相对简单。直接枚举起点跑就行。

设 \(f_{i,j}\) 表示在 \(A\) 中到第 \(i\) 位,在 \(B\) 中到第 \(j\) 位的答案。

那么 \(f_{i,j}=\min\{f_{\delta(i,c),\delta(j,c)}+1\}\)

KMP

设 \(\mathrm p_i\) 表示前 \(i\) 位最长相同真前后缀长度。

对于字符串 \(\texttt{abbaabb}\)

  1. \(\mathrm p_1=0\):\(\texttt{a}\)
  2. \(\mathrm p_2=0\):\(\texttt{ab}\)
  3. \(\mathrm p_3=0\):\(\texttt{abb}\)
  4. \(\mathrm p_4=1\):\(\underline{\texttt{a}}\texttt{bb}\underline{\texttt{a}}\)
  5. \(\mathrm p_5=1\):\(\underline{\texttt{a}}\texttt{bba}\underline{\texttt{a}}\)
  6. \(\mathrm p_6=2\):\(\underline{\texttt{ab}}\texttt{ba}\underline{\texttt{ab}}\)
  7. \(\mathrm p_7=3\):\(\underline{\texttt{abb}}\texttt{a}\underline{\texttt{abb}}\)

处理出 \(\mathrm p_i\) 有什么用呢?

模式串在匹配文本串的时候,如果是以下这个状态:

v5HMNR.png

发现到第五位时失配了,我们接下来肯定是想让它从蓝色这个状态继续匹配。

可以发现,跳到 \(\mathrm p_i\) 一定不劣。即比如在第五位失配了,就跳到 \(\mathrm p_4=1\) 位,如果跳到这里发现可以匹配下去,由于前后缀相同,所以可以继续匹配下去。如果不能匹配下去,那就继续往前跳。

由于每次只往后移动一格,往前跳的次数一定小于等于往后走的次数,复杂度 \(O(n)\)。

怎么求 \(\mathrm p\) 呢。

v5bZGt.png

假设当前位是 \(i\),\(\mathrm p_{i-1}=j\)。如果 \(\mathrm p_i>\mathrm p_j\),那么 \(\mathrm p_i=\mathrm p_j+1\) 且 \(S_{j+1}=S_i\)。

否则,贪心地令 \(j=\mathrm p_j\),即上图绿框,可以发现如果此时 \(S_{j+1}=S_i\) 还是可以下去且最优。

最后,不难发现 kmp 的过程与求 \(\mathrm p\) 的过程类似,代码:

int j=0;
for(int i=2;i<=m;i++){
    while(j&&b[i]!=b[j+1])j=pre[j];
    j+=(b[i]==b[j+1]);pre[i]=j;
}
j=0;
for(int i=1;i<=n;i++){
    while(j&&a[i]!=b[j+1])j=pre[j];
    j+=(a[i]==b[j+1]);
    if(j==m)write(i-m+1,'\n'),j=pre[j];
}

KMP自动机

用 KMP 建出的自动机,转移:

\[\delta(x,c)=\begin{cases} x+1&S_{x+1}=c\\ 0&i=0\land S_1\neq c\\ \delta(\mathrm p_x,c)&i>0\land S_{x+1}\neq c\\ \end{cases} \]

[HNOI2008]GT考试

求有多少个 \(N\) 位数字文本串满足:没有一个子串为给定模式串。

模式串长度为 \(M\),对 \(K\) 取模。

\(N\leq10^9,M\leq20,K\leq1000\)

solution

dp,设 \(f_{i,j}\) 表示文本串中匹配到第 \(i\) 位,模式串中匹配到第 \(j\) 位的方案数。

那么:

\[\begin{aligned} f_{i,j}=&\sum _c\sum_{k,\delta(k,c)=j}f_{i-1,k}\\ =&\sum_{k}f_{i-1,k}\sum _c[\delta(k,c)=j]\\ \end{aligned} \]

设矩阵 \(g\) 有: \(\displaystyle g_{k,j}=\sum _c[\delta(k,c)=j]\),就可以把转移看做向量乘上矩阵。

又发现 \(g\) 与 \(i\) 无关,于是矩阵快速幂。

失配树

border

任意长度相同前后缀。

失配树

考虑一个问题:

【模板】失配树

给定 \(S\),\(T\) 次询问 \(p,q\),求 \(p\) 前缀和 \(q\) 前缀的最长公共 border。

首先,根据 KMP 中 \(\mathrm p_i\) 的定义,从一个点开始不断往上跳 \(\mathrm p_i\),跳到的就是它的所有 border。

而仔细思考后发现一个点向它的 \(\mathrm p_i\) 连边,连出来的就是一个树形结构,我们称其为失配树。

而两段前缀的最长公共 border 转化为了失配树上的 LCA。

[NOI2014] 动物园

求出对于 \(S\) 每个前缀的不相交 border 个数。

对于一个前缀 \(S[1,i]\) 求不相交 border 可以转化为长度 \(\le \frac{i}2\),所以我们就可以在失配树上往上跳,跳到符合条件,深度就是答案。

可以不用显式建树。

Z 函数

令 \(\mathrm z_i\) 表示一个字符串 \(s\) 和 \(s[i,n]\) 的 LCP,特别的,\(\mathrm z_1=0\)。

对于字符串 \(\texttt{aaabaab}\)

  1. \(\mathrm z_1=0\):
  2. \(\mathrm z_2=2\):\(\underline {\texttt{a}\underline{\texttt{a}}}\underline{\texttt{a}}\)
  3. \(\mathrm z_3=1\):\(\underline {\texttt{a}}\texttt{a}\underline{\texttt{a}}\)
  4. \(\mathrm z_4=0\):
  5. \(\mathrm z_5=2\):\(\underline{\texttt{aa}}\texttt{ab}\underline{\texttt{aa}}\)
  6. \(\mathrm z_6=1\):\(\underline{\texttt{a}}\texttt{aaba}\underline{\texttt{a}}\)
  7. \(\mathrm z_7=0\):

Z 函数其实也很好求:

从某个位置 \(i\) 开始,与整串前缀相同的前缀(称为 Z-box)为 \(s[i,i+\mathrm z_i-1]\)。

我们维护当前 \(i+\mathrm z_i-1\) 的最大值 \(r\),以及其对应的 \(i\) ,令其为 \(l\)。

假设我们已经求出 \(1\sim i-1\) 的 Z 函数,接下来要求 \(\mathrm z_i\)。

根据定义,有 \(s[i,r]=s[i-l,r-l]\),所以,\(\mathrm z_i\ge\min({\mathrm z_{i-l}},r-i+1)\)。

如果还有机会继续拓展(\(r-i+1\le \mathrm z_{i-l}\)),那就右移 \(r\),否则就 G 了。

l=1,r=0;
for(int i=2;i<=m;i++){
    if(i<r)z[i]=min(z[i-l+1],r-i+1);
    while(i+z[i]<=m&&b[i+z[i]]==b[z[i]+1])++z[i];
    if(i+z[i]-1>=r)r=i+z[i]-1,l=i;
}

匹配另一个串

拼起来再做一遍即可。

但是注意拼起来时中间放一个随便什么引荐字符,避免匹配到后面的串。

[NOIP2020] 字符串匹配

给字符串 \(S\),求 \(S = {(AB)}^iC\) 的方案数,设 \(F(S)\) 表示 \(S\) 中出现奇数次的字符数量,有 \(F(A)\le F(C)\)。定义乘法为前后拼接。

solution

枚举循环节长度:

如图为长度为 \(i-1\) 的循环节,不难发现有颜色的段是完全相同的,而且不能再往后延伸一段。

可以得出,最大循环节段数为 \(t_i=\displaystyle\left\lfloor\frac{\mathrm z_i}{i-1}\right\rfloor+1\)。注意:为了最后留至少一个字符给 \(C\),所以如果循环节把整串排满了,要 \(-1\)。

设 \(pre_i\) 表示 \(S[1,i]\) 中出现奇数次的字符数量,\(suf_i\) 表示 \(S[i,n]\) 中出现奇数次的字符数量。

对循环节段数 \(k\) 奇偶分类讨论:

  • \(k\equiv1\pmod 2\)

    不难发现,段数为奇数时,\(F(C)\) 保持不变(两个不同的奇数 \(k\) 对应的串 \(C\) 只差偶数段循环节,正好抵消了)。

    所以,我们只要找到 \(S[1,j](j<i)\) 使得 \(F(A)=pre_j\le F(C)=suf_i\)(算 \(k=1\) 时的 \(F(C)\))。

    这部分的贡献为:满足条件的 \(j\) 的个数 \(\times\) 满足条件的 \(k\) 的个数。

  • \(k\equiv0\pmod 2\)

    段数为偶数时 \(F(C)\) 也保持不变(原因同上),且等于 \(suf_1\)。

    所以,我们只要找到 \(S[1,j](j<i)\) 使得 \(F(A)=pre_j\le F(C)=suf_1\)。

    这部分的贡献为:满足条件的 \(j\) 的个数 \(\times\) 满足条件的 \(k\) 的个数。

然后发现做完了。

标签:忘光,复习,后缀,texttt,link,endpos,STR,operatorname,mathrm
From: https://www.cnblogs.com/TOBapNwCJN/p/17188344.html

相关文章

  • 自从用了 Stream,代码更简洁优雅了!
    来源:blog.csdn.net/qq_41698074/article/details/108502976前言虽然stream在Java8中就已经被引入,但是大多数人却没有去使用这个十分有用的特性,本文就通过介绍几个通过......
  • 忘光了,所以复习【GRU】
    群论基本代数系统:非空集\(G\)以及一堆二元运算组成一个代数系统,表示为\((G,\cdots,\cdots)\),其中后面表示每个运算的符号。群:代数系统\((G,\cdot)\)(称作乘法),满足以......
  • 封装bootstrap的Toasts组件实现的多个下载任务弹框
    最近要改一个下载任务的需求,原来的代码要么使用ajax异步请求看不到下载进度,要么使用window.open(url,‘__blank’)打开一个新页面既看不到下载进度也要手动关闭新打开的窗口......
  • HCIP-HCIA的复习(二)
     一、DHCP服务---动态主机配置协议DHCPDiscover---广播应用层 DHCPDicover传输层UDP---源端口号68---目的端口号67 网络层IP---源IP地址......
  • 76. Minimum Window Substring
    76.MinimumWindowSubstring标签(空格分隔):leetcodehard题目GivenastringSandastringT,findtheminimumwindowinSwhichwillcontainallthec......
  • 106. Construct Binary Tree from Inorder and Postorder Traversal
    题目Giveninorderandpostordertraversalofatree,constructthebinarytree.Note:Youmayassumethatduplicatesdonotexistinthetree.思路本题......
  • C# 字符串(String)的使用
    C#字符串(String)的使用本文主要介绍C#中字符串(String)的基础使用操作和相关方法使用(为变量分配字符串、字符串长度、字符串方法、、字符串连接、字符串格式化......
  • Android systrace命令行工具
    命令行工具systrace(SystemTrace)跟踪的是系统级的内容,如CPU各核心调度,SurfaceFlinger、VSync(垂直同步)、BufferQueue。通过收集系统事件和App逻辑中插入的自定义事件的组合......
  • 面试复习总结-tcp三次握手四次挥手
    1.TCP/IP协议:应用层:HTTPFTPTFTPHTTPS会话层表达层传输层:TCPUDP网络层:IPICMPARP 数据链路层:PPP,PPTP物理层:帧 tcp三次握手四次挥手: 1.客户端发送连接......
  • hard-coded strings are a bad idea.
    Hard-Codingisaterriblybadpractice. Lookatthecodebellow. Theprogrammerhardcodedthestringsintheprogram. Stringlike "huiQiTransPaymentSer......