RemoteJudge
题目大意
给你一个串\(S\)以及一个字符串数组\(T[1...m]\),\(q\)次询问,每次问\(S\)的子串\(S[p_l...p_r]\)在\(T[l...r]\)中的哪个串里的出现次数最多,并输出出现次数。
如有多解输出最靠前的那一个。
思路
第一次见到在\(parent tree\)上线段树合并的题,感觉好妙
先对\(T\)建一个广义后缀自动机,考虑对\(SAM\)上的每一个结点建一颗线段树,值域为\([1,m]\),维护出现次数最多的串的位置和次数。又因为\(endpos\)集合(好像也叫\(right\)集合)有这么一个性质:一个结点的\(endpos\)集合即为其在\(parent\ tree\)上子结点的并集,所以我们在建树时只需要上一个线段树合并即可。
上面的那个思路貌似是个套路?
然后来处理询问,显然我们只需要在\(S[p_l...p_r]\)对应的结点的线段树上查\(l-r\)的最大值就行了,但如果直接拿\(S[p_l...p_r]\)在\(SAM\)上匹配,复杂度绝壁不对QwQ。于是我们考虑先把整个\(S\)在\(SAM\)上匹配,需要查哪个子串时通过跳\(suflink\)来找。具体一下,就是对于\(S\)的一个前缀\(S[1...j]\),如果它最后匹配到了结点\(u\),匹配的长度为\(len\),然后我们要查的子串是\(S[i...j]\),就从\(u\)开始跳\(suflink\)直到一个\(maxlen\)大于等于\(j-i+1\)且深度最小的结点,记其为\(v\),要查的就是\(v\)那棵线段树的答案
最后发现跳\(suflink\)的过程可以用倍增来优化,然后就没了
吐槽1.为什么我写离线的就会\(WA\),在线的就过了
吐槽2.下午三点多写完,然后\(CF\)
咕到了六点多,然后交了一发,\(WA\)了,我...
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include