于是现在问题变为快速合并两个结点的信息,我们考虑维护每个结点 x 所对应的字符串 s_x 中,模式串 p 的出现次数,以及 s_x 最长的在 p 中作为子串出现过的前缀和后缀(并把它们在 p 中出现位置的左右端点记录下来,如有多个,随便记录一个即可)。
我们建出 p 的后缀数组,合并的时候,对于最长的出现过的前缀,我们考虑二分出它在 p 所有后缀中的排名。比较大小时,我们相当于要比较 p[l_1,r_1]+p[l_2,r_2] 和 p 的一个后缀的大小关系,只需先求出 LCP,然后比较下一位字符的大小即可。然后再求出 p[l_1,r_1]+p[l_2,r_2] 与它在后缀数组中前驱后继的 LCP,较长的那个即为最长的出现过的前缀,后缀的求法是同理的,只需对反串建立后缀数组。
我们还需统计跨越合并位置的 p 的出现次数,设我们合并的是 x,y 两个点,则我们只需求出 s_x 的一个最长后缀,使得它是 p 的一个前缀,和 s_y 的一个最长前缀,使得它是 p 的一个后缀。
我们以 s_y 为例,先二分出它在 p 后缀数组中的排名,然后求出它与前驱的 LCP,设 LCP 的长度为 len,则我们只需求出这个前驱的最长的长度 \le len 的 Border,这可以在失配树上倍增得到。