GRE Words

我永远喜欢数据结构。

UVA1502 / SP9941

  • 给出 \(n\) 个字符串 \(s_1\sim s_n\),第 \(i\) 个字符串有权值 \(w_i\)。选出一个子序列 \(a_1\sim a_k\),满足 \(\forall\,i\in[1,k),a_i<a_{i+1}\)\(s_{a_i}\)\(s_{a_{i+1}}\) 的子串。求 \(\sum\limits_{i=1}^kw_{a_i}\) 的最大值。可以为空,此时权值为 \(\boldsymbol 0\)

  • \(T\) 组数据,\(T\le 50\)。对于单组数据,满足 \(n\le 2\times 10^4\)\(\sum\limits_{i=1}^n|s_i|\le 3\times 10^5\)

\(N=\sum\limits_{i=1}^n|s_i|\)

考虑 dp。设 \(f_i\) 表示以 \(i\) 开头的最长子序列,则 \(f_i=\max\limits_{j\in(i,n]\land \,s_i\text{ is a substring of }s_j} f_j+w_i\)

将所有串拼成一个大串 \(S\) 进行后缀排序。则 \(j\) 满足条件,当且仅当 \(s_j\) 中有一个后缀与 \(s_i\) 的最长公共前缀长度不少于 \(|s_j|\)

这样的后缀排名形如一个区间 \([L,R]\)。考虑线段树维护。区间 \([l,r]\) 的信息为:当前包含排名为 \([l,r]\) 中的后缀的字符串中,\(f_j\) 的最大值。

那么转移就是区间最大值。可能会重复贡献一些 \(f_j\),但由于是取 \(\max\) 所以没关系。

转移完后在线段树上对 \(s_i\) 的所有后缀排名对应的位置进行单点修改。

时空复杂度均为 \(\mathcal{O}(N\log N)\)。可以把 \(\text{height}\) 数组用线段树维护然后线段树上二分得到排名区间,这样空间是线性。

AC Link / AC Code

posted @ 2024-03-10 14:53  蒟蒻·廖子阳  阅读(7)  评论(0编辑  收藏  举报