以前做的,没发博客。
如果两个串的 endpos
等价类相同,显然把任意一个放进 si 里面是一样的效果。
于是我们可以建出 SAM
的 fail
树,考虑做 dp[u] 表示当前在树上的 u 节点,同时我们最后一次选择的是这个点上的最长串,最多可以选出的序列长度。
显然,我们选择一个深度更大的位置比选择一个深度更小的位置作为序列的上一个位置好。因为深度更小的位置一定在深度更大的位置的所有 endpos
中出现过。所以我们可以考虑找到最深的一个位置,满足这个位置在当前串中出现过至少两次。
我们可以进行可持久化线段树合并,然后倍增来跳这个位置。如果一个位置 v 满足,即意味着在 rt[v] 的线段树里面在 [r−len[u]+len[v],r−1] 之间有过值,也就是有过 endpos
。
直接进行线段树区间查询即可。
cpp
1 |
|