Border & $\pi$ 函数
一些定义
-
字符串 $S$ 的真前/后缀为非自身的前/后缀
。 -
字符串 $S$ 的 border为 $S$ 的公共真前/后缀
。 -
字符串 $S$ 的最长 border 为 $\pi$
对于 $S$ 的每个前缀 $S_{1 \sim i}$ 令 $\pi_i$ 为其最长 border, $\pi$ 函数就是所谓的前缀函数, 。
$\pi$ 函数的性质
- $\forall i,\pi_{i+1}\leqslant \pi_i+1$
。
由反证法易知
。
- 字符串 $S$ 的所有 border 可以由 $\pi_{|S|}$ 开始不断跳 $\pi$ 由长度从大到小遍历
。
只需证明 $S_{1 \sim \pi_{\pi_n}}$ 是 $S$ 的次长 border 即可
。 由 $\pi$ 的定义易知
。
- 相邻前缀函数满足 $\pi_{i + 1} = \max\limits_{T ~ is ~ the ~ border ~ of ~ S_{1 \sim i}, S_{i + 1} = S_{|T| + 1}} |T| + 1$
。
使用反证法易知
。
$\pi$ 函数的线性求法
有了上述几条性质
pi[0] = -1;
for (int i = 1; i <= n; i++)
for (int j = pi[i - 1]; j >= 0; j = pi[j])
if (s[j + 1] == s[i]) { pi[i] = j + 1; break; }
直观感受上这个做法是 $\Theta(n ^ 2)$ 的
不难发现复杂度来源在于跳 $\pi$
下面我们将证明跳 $\pi$ 的总次数是线性的 , 。 注意 $\pi_i$ 的位置变化情况
不难发现 $\pi_i$ 只会每次 $+1$ 或往前跳若干次 , 但往前跳的的总距离不能超过当前 $+1$ 的次数 , 故总路程也是线性的 , 。
$\pi$ 函数的基本应用
字符串匹配
求解模式串 $T$ 在匹配串 $S$ 中的出现位置的问题
构造一个新的字符串 $T\circ S$
对这个新的字符串求其 $\pi$ 函数
以上即为 $\rm KMP$ 算法
统计每个前缀的出现次数
考虑到如果某个前缀在之后的位置里出现过
for (int i = 1; i <= n; i++) ans[i] = 1;
for (int i = n; i >= 1; i--) ans[pi[i]] += ans[i];
至于这个问题的加强版
统计本质不同子串的数目
考虑迭代计算
如果一个子串 $S_{i\sim n}$ 在前面出现过
由反证法易知
。
于是就只需求出加入新字符后的串的反串中的 $\max\pi$ 即可
字符串周期相关性质
称 $k$ 为 $S$ 的一个周期且仅当 $\forall i\leqslant |S|-k, S_i = S_{i + k}$
- 若字符串 $S$ 存在一个 border $T$
当且仅当 $S$ 存在一个长度为 $|S| - |T|$ 的, 弱( 周期) 。
必要性显然
充分性递归论证即可 , 。
- 字符串 $S$ 的最短
弱( 周期长度为 $n - \pi_n$) 。
由 $\pi$ 函数的定义易知
。
- 若长度不小于 $p + q$ 的字符串 $S$ 存在长度分别为 $p, q$ 的
弱( 周期) 那么 $\gcd(p, q)$ 也是 $S$ 的一个, 弱( 周期) 。
下面首先证明 $p - q(p > q)$ 也是 $S$ 的一个
弱 ( 周期 ) 。 分两种情况讨论
:
若 $i \leqslant q$
则 $S_i = S_{i + p} = S_{i + p - q}$ , 可知 $\forall i \leqslant q, p - q$ 是其一个 , 弱 ( 周期 ) 。 若 $i > q$
则 $S_i = S_{i - q} = S_{i + p - q}$ , 可知 $\forall i > q, p - q$ 是其一个 , 弱 ( 周期 ) 。 证明 $p - q$ 是 $S$ 的一个
弱 ( 周期后 ) 根据更相减损术的性质 , 最终可以迭代至 $\gcd(p, q)$ 是 $S$ 的一个 , 弱 ( 周期 ) 。
- 所有强周期的长度均为最短强周期长度的倍数
。
若存在一个强周期 $x$
显然有 $x\mid n$ , 若 $n-\pi_n\nmid x$ , 则 $\gcd(n-\pi_n,x)<n-\pi_n$ 也为一个强周期 , 与 $n-\pi_n$ 是最小强周期矛盾 , 。
- 字符串 $S$ 存在周期当且仅当 $n - \pi_n$ 为一个周期
。
必要性显然
若存在强周期 $x\mid n$ 。 又因为 $n-\pi_n\mid x$ , 则 $n-\pi_n\mid n$ , 充分性得证 , 。
KMP 自动机
在求 $\pi$ 函数的时候
并且在做 $\rm KMP$ 的过程中我们发现
这意味着可以对一个模式串建立一个自动机
但是实际上之前已经计算了从所有节点开始
同 $\rm KMP$ 算法一样
另一方面
定义 $g_1="a"$
显然题目是要求从 $0$ 号节点开始对 $g_k$ 进行匹配
首先对 $S$ 建立 $\rm KMP$ 自动机
总时间复杂度 $\Theta(|S|\times k)$
另外
考虑对模式串建立 $\rm KMP$ 自动机
令 $f_{i,j}$ 表示对字符串匹配到第 $i$ 位时
由于 $\rm DP$ 空间开不下
时间复杂度 $\Theta(|S||T||\Sigma|)$