Loading

连接字符串 题解

连接字符串 题解

题面描述

你有两个小写字母串 \(S\)\(T\) 。令 \(f(S)\) 表示 \(S\) 中所有不同的非空子串形成的集合。
\(G\) 表示所有 \(s\in f(S),t\in f(T)\)\(s+t\) 形成的多重集。问 \(G\) 中字典序第 \(k\) 小串。

\(|S|,|T|\le 75000\)

题解

字符串字典序考虑逐位枚举确定。

建出 \(S,T\) 的后缀自动机,记从 \(u\) 开始的路径数为 \(cnt_u\)

若现在已经找到了 \(ans\) 的一个前缀 \(pre\),现在要确定这个以 \(pre\) 为前缀的 \(G\) 中元素个数,设在 \(samS\) 上匹配 \(pre\) 的最长前缀走到节点 \(u\)\(samT\) 上匹配 \(pre\) 的最长后缀走到节点 \(v\),分为两种情况:

  • \(pre\)\(S\) 的子串,那么有 \(cnt_u\times |samT|\) 的方案

  • \(pre\)\(S\) 的字串与 \(T\) 的子串拼接,设 \(s\) 是匹配的最长前缀,\(t\in f(T)\land t\)\(pre\) 后缀,那么只要 \(|t|+|s|\ge |pre|\)\(t\) 就是合法的,设 \(w\) 是第一个包含不合法 \(t\)\(v\) 的祖先那么能算进答案的就是 \(w\) 代表串的后缀到 \(v\) 代表串的前缀。

只要我们能不断维护 \(u,v,w\) 就可以算出次数。

具体方法:

  1. 预处理出 \(trans[u][c]\) 表示从 \(u\) 节点时又来一个 \(c\) 时转移到的位置,类似AC自动机。

  2. \(u\) 只走 \(trie[u][c]\) 走不动就不走,\(v,w\) 都走 \(trans[u][c]\) 且若 \(w\) 代表的节点太长要向上跳 \(fail\)

  3. 可以发现 \(v,w\) 是单独更新的,如果通过 \(v\) 用倍增算 \(w\),会有 $\log $ 的复杂度。

最终复杂度 \(\mathcal O(n|\Sigma|)\),处理一个节点代表的串的前后缀时有一堆细节。

posted @ 2025-05-05 09:16  lupengheyyds  阅读(13)  评论(0)    收藏  举报