再谈字符串

今天对字符串有了一点新的理解,遂再写一篇博客。

字符串取模

定义

可以参考 我之前写的博客。不再赘述。下文用长度表示。

运算

( S + c ) ≡ ( S   m o d   P ) + c ( m o d P ) (S+c) \equiv (S \bmod P) + c \pmod P (S+c)≡(SmodP)+c(modP)

KMP

定义 g o ( i , c ) go(i, c) go(i,c) 函数,表示 P P P 的 i i i 前缀添加字符 c c c 的字符串的模 P P P 值。定义失配函数(fail) f i f_i fi 表示 P P P 的 i i i 前缀时增加的字符 c c c 失配的模 P P P 值。

g o ( i , c ) = { i + 1 P i = c g o ( f i , c ) P i ≠ c go(i, c) = \begin{cases} i+1 & P_i =c\\ go(f_i,c) & P_i \ne c \end{cases} go(i,c)={i+1go(fi,c)Pi=cPi=c

cpp 复制代码
int go(int i, char c)
{
	if(P[i] == c) return i + 1;
	if(i == 0) return 0;
	return go(f[i], c); 
}

...

for(int i=0; i<P.size(); i++)
	f[i+1] = go(f[i], c); // 这里 

fail 数组分析

关于 f i f_i fi,一方面从自动机角度考虑,即 π i \pi_i πi。

一方面从字符串取模的角度考虑, f i = P [ 1.. i ) f_i=P[1..i) fi=P[1..i) 模 P P P 值。那么 P [ 0... f i ) ≡ P [ 1... i ) ( m o d P ) P[0...f_i) \equiv P[1...i) \pmod P P[0...fi)≡P[1...i)(modP),发现 f i f_i fi 同样满足 π i \pi_i πi 的性质。

复杂度分析

对于一般的 KMP 问题,设文本串长 n n n,模式串长 m m m。

cpp 复制代码
int cur = 0;
for(int i=0; i<text.size(); i++)
{
	cur = go(cur, text[i]);
	...
}

首先有 f i < i f_i < i fi<i。文本字符可能提供当前字符串模 P P P 后的长度,至多增加 n n n 次。因此复杂度是线性的。


无限猴子类技巧

问题形如出现某个模式串 P P P 的期望长度。

由于只关心匹配,考虑只关心模 P P P 的值,据此结合待定系数法做期望 dp 即可。

例题

Censoring S

无限猴子

[CTSC2006] 歌唱王国


清除模式类技巧

如题,清除字符串中的模式串 P P P。

逐位枚举,考虑当前字符串模 P P P 的值即可。

例题

清除模式

Pareidolia G

相关推荐
樱木Plus1 天前
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
c++
blasit3 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_4 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星4 天前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛6 天前
delete又未完全delete
c++
端平入洛7 天前
auto有时不auto
c++
哇哈哈20218 天前
信号量和信号
linux·c++
多恩Stone8 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马8 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost
超级大福宝8 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode