题目描述:
n
≤
1
0
5
,
w
i
<
n
n\le10^5,w_i<n
n≤105,wi<n,LOJ题目链接
题目分析:
看到两个后缀的LCP就想到后缀自动机或者后缀数组
先从后缀自动机的思路入手,我们知道两个后缀的LCP就是它们在后缀自动机fail树上的LCA的len。
所以这道题就变成了:在fail树上,求
u
u
u点的不同子树内的
w
i
xor
w
j
w_i~\text{xor} ~w_j
wi xor wj的最大值。
需要Trie树合并,查询异或最大值。
合并的话,可以启发式合并(暴力插入),但是需要遍历子树内的点,查询也可以暴力遍历小的子树到大的子树里面查询,但是空间复杂度是
O
(
n
log
2
n
)
O(n\log^2n)
O(nlog2n)的,可以改为树上DSU,空间复杂度降为
O
(
n
log
n
)
O(n\log n)
O(nlogn),时间复杂度
O
(
n
log
2
n
)
O(n\log^2n)
O(nlog2n),比如这份提交。
但是Trie树合并可以像线段树合并一样,并且因为不需要可持久化,所以合并的空间和时间复杂度都可以降为
O
(
n
log
n
)
O(n\log n)
O(nlogn)。
查询的话也不需要遍历子树,因为是查两棵Trie树异或出的最大值,在两棵树同一层的点对
(
x
,
y
)
(x,y)
(x,y),对于
l
c
[
x
]
lc[x]
lc[x],它优先会选择
r
c
[
y
]
rc[y]
rc[y],如果没有
r
c
[
y
]
rc[y]
rc[y]则会选择
l
c
[
y
]
lc[y]
lc[y],也就是说
l
c
[
x
]
lc[x]
lc[x]所对应的第二棵树的节点是确定的,所以dfs求解的点对数就是小的Trie树里的点数。
这个写法可以参见我的提交。
后缀数组的解法可以根据height值建出笛卡尔树,查询就暴力遍历小子树的点到大子树的Trie中查询。
但是此时的Trie树实际上是一个区间,于是可以用类似主席树的形式写可持久化Trie树然后做差,比如这份提交。