首页 > 其他分享 >字符串

字符串

时间:2023-10-19 22:34:13浏览次数:36  
标签:nxt 匹配 sum len 字符串 回文

约定

\(S/s\) :字符串。

\(S[l,r]\):区间 \([l,r]\) 形成的子串。

\(S^R\):将字符串 \(S\) 翻转。

manacher

理论

字符串算法的精髓是最大的利用之前求出的信息,这就让增量法和自动机成了字符串算法中的核心思想。

manacher 算法可以在线性时间复杂度内求出以每个点为中心的极大回文子串长度。

算法实现中我们维护:

  • mid:当前最大的回文子串的中心。
  • r:当前最大的回文子串的右端点。
  • \(len_i\):以 \(i\) 为中心的回文半径。

考虑到回文串的长度有奇有偶,我们选择在每两个字符间插入一个无关字符,这样奇偶回文串的长度就都变成了 \(len_i - 1\)。

如果 \(i \lt r\),即 \(i\) 在当前的最大回文串的影响范围内,因为当前串是关于 \(mid\) 对称的,所以可以用 \(i\) 关于 \(mid\) 的对称点的回文半径更新 \(i\),并且要注意不能超出边界即 \(len_i = min(len_{mid * 2-i},r-i+1)\),剩下的暴力匹配即可。

因为每次 \(r\) 至少右移 \(1\),所以复杂度是线性的。

for(int i = 1; i <= n; i++){
    if(i <= r) len[i] = min(r - i + 1, len[(mid << 1) - i]);
    while(s[i-len[i]] == s[i+len[i]]) len[i]++;
    if(i + len[i] > r){
        mid = i;
        r = i + len[i] - 1;
    }
}

例题

Extend to Palindrome

最终的答案形如 \(S + pres_i^R\),满足 \(pres_i\) 为回文串,要尽量缩小 \(pres_i\) 的长度,也就是找到最靠前的回文子串满足其右端点是原串的右端点。

P3501 [POI2010] ANT-Antisymmetry

类似于正常的 manacher 过程,只不过两个字符匹配的条件变成了 xor 等于 \(1\)。

KMP

理论

定义 \(nxt_i\) 表示 \(S[1,i]\) 的最长公共前后缀,首先考虑如何快速的求出一个字符串的 \(nxt\) 数组。

考虑 DP,\(nxt_i\) 仅可以从 \(S[1,i-1]\) 的公共前后缀转移过来,找到最大的可以接上 \(S_i\) 的 \(nxt\) 这个过程可以一直跳 \(nxt\) 实现,原理如下图:

tmpe

因为 \(j\) 每次最多增加 \(1\),复杂度最大的时候就是从 \(n\) 跳回 \(0\),这样是线性的。

匹配的过程和求 \(nxt\) 类似,如果当前位置失配就跳 \(nxt\),这样充分利用了一个串的信息,保证文本串的指针不会后移,所以复杂度也是线性的。

多项式在字符串匹配中的应用

考虑两个数相等的条件是什么 -> \(a-b = 0\),那把这个东西放到字符串上就有了代数意义上的两个字符相等的判断依据:字符的匹配函数 \(cmp(x,y) = A_x - B_y\),\(cmp(x,y) =0\) 说明 \(A_x = B_y\)。

有了这个东西后再定义一个字符串完全匹配函数:\(P(n) = \sum_{i=0}^{m-1}cmp^2(i, n-m+1+i)\),\(P(n) = 0\) 说明以 \(n\) 为结尾,字符串 A 在字符串 B 中出现。至于为什么加平方?如果不加的话会出现正负相消的情况,只要两个字符串的字符集一样两个串就匹配了,不合法呢。

为了凑出好看的形式,我们将 \(A\) 翻转并用 \(i\) 代替 \(m - i - 1\),有:

\[\begin{split} P(n) &= \sum_{i=0}^{m-1} (A_i- B_{n-i})^2\\ &= \sum_{i=0}^{m-1}A_i^2 + \sum_{i=0}^{m-1}B_{n-i}^2 - 2\sum_{i=0}^{m-1}A_iB_{n-i} \end{split} \]

这就出来卷积式了,虽然上界比较迷,但是问题不大,直接大力出奇迹设成 \(max(n,m)\)。

这个东东还可以用来做通配符匹配:P4173 残缺的字符串

考虑通配符怎么搞?相当于强制把匹配函数的值设成零,一种方法是 \(cmp(x,y) = A_xB_y(A_x-B_y),'*' = 0\) ,这样通配符对应的匹配函数值一定是 \(0\)。推式子也和上面一样大力展开即可,这里就不写了。

例题

String Factoring

设 \(dp_{i,j}\) 表示 \([i,j]\) 的最短 \(Factoring\) 的长度,转移:\(dp_{i,j} = min(dp_{i,k},dp_{k+1,j})\),考虑一个串的压缩相当于是找出最小的周期且这个串能恰好被表示成这个周期的若干倍,以周期来代替这个串,根据一些 \(border\) 的理论,一个串的最小周期是 \(n - nxt_{n}\),直接做即可。

标签:nxt,匹配,sum,len,字符串,回文
From: https://www.cnblogs.com/Lkkaknoi/p/17775849.html

相关文章

  • javascript如何写不用转义的字符串代码
    js中的String.raw函数 语法 String.raw`templateStr`;  String.raw(obj,...substitutions); 支持能力有限,如可以支持String.raw`c:\aaa\bbb`       //result:   c:\aaa\bbb 但是String.raw`c:\aaa\bbb\`       //result:  ......
  • Linux shell编程学习笔记8:使用字符串
    一、前言字符串是大多数编程语言中最常用最有用的数据类型,这在Linuxshell编程中也不例外。本文讨论了LinuxShell编程中的字符串的三种定义方式的差别,以及字符串拼接、取字符串长度、提取字符串、查找子字符串等常用字符串操作,,以及反引号在echo和expr命令联合使用时的作用。二......
  • Python中如何将字符串变成数字?
    字符串和数字是Python中常见的数据类型,而且在撰写Python程序的时候,也经常会遇到需要将字符串转换为数字的情况,那么Python中如何将字符串变成数字?有多种方法可以使用,接下来一起来看看具体内容介绍。1、使用int()函数int()函数可以将字符串转换为整数类型。例如,将字符串......
  • C# 中的字符串内插 $对比string.Format
    原文:https://blog.csdn.net/HeBizhi1997/article/details/123544524C#10.0对字符串插值做了点提升,支持开发人员对字符串进行花式内插。附官方教程:https://docs.microsoft.com/zh-cn/dotnet/csharp/tutorials/string-interpolation#code-try-0icon-default.png?t=M2......
  • 代码训练营第八天(Python)| 344.反转字符串、541. 反转字符串II、05.替换空格、151.翻转
    344.反转字符串双指针法时间复杂度为:O(n),空间复杂度为:O(1)classSolution:defreverseString(self,s:List[str])->None:"""Donotreturnanything,modifysin-placeinstead."""left,right=0,len(s......
  • Java 新手如何使用Spring MVC 中的查询字符串和查询参数?
    Java新手如何使用SpringMVC中的查询字符串和查询参数?根据维基百科的说法,“查询字符串是统一资源定位符(URL)的一部分,它为指定的参数分配值。查询字符串通常包括由Web浏览器或其他客户端应用程序添加到基本URL的字段,例如作为HTML的一部分、选择页面的外观或跳转到多媒体内容......
  • 字符串拼接小技巧
    常用写法下:Stringname=name+"("+id+")"像上面这种情况可以使用String.format()快速实现字符串的拼接:Stringname=String.format("%s(%s)",name,id.toString());......
  • 找到s字符串中的回文子串
    #coding=utf-8#找到s字符串中的回文子串s="abbc"#n=len(s)#result=''#foriinrange(n):##print(i)#forjinrange(i,n):##print(j)#k=s[i:j+1]##print(k)##print(k[::-1])#ifk==k......
  • redis普通连接和连接池, redis字符串类型,redis hash类型, redis列表类型
    1redis普通连接和连接池......
  • delphi 判断字符串里的char是单字节还是双字节的前一位或后一位。
    function  ByteType(const  S:  string;  Index:  Integer):  TMbcsByteType;  // 判断一个字符串中,某个 Char 是单个字母,还是双字节的前一位或后一位。  // mbSingleByte单字母  // mbLeadByte  双字节第一位  // mbTrailByte ......