正题 题目链接:https://www.luogu.com.cn/problem/CF204E 题目大意 \(n\)个字符串的一个字符串集合,对于每个字符串求有多少个子串是这个字符串集合中至少\(k\)个字符串的子串. 解题思路 因为对于每个字符串我们需要维护的信息不同,不能累加,所以考虑使用线段树合并. 先将\(n\)个字符串构建出一个广义\(SAM\),然后对于每个节点维护一个该线段树表示该节点属于的字符串.然后在\(parents\)树上从下往上合并,如果属于字符串的数量多余\(k\),那…
正题 题目链接:https://www.luogu.com.cn/problem/CF666E 解题思路 给出一个串\(S\)和\(n\)个串\(T_i\).\(m\)次询问\(S_{a\sim b}\)在\(T_{l\sim r}\)中出现的最多次数并且输出这个串的编号. \(1\leq |s|\leq 5\times 10^5,\sum T_i\leq 5\times 10^4,1\leq m\leq 5\times 10^5\) 解题思路 把\(S\)和\(T\)丢一起跑一个广义\(SAM…
正题 题目链接:https://www.ybtoj.com.cn/problem/532 题目大意 给出\(n\)个点的一个\(Trie\)树,定义\(S_x\)表示节点\(x\)代表的字符串 求$$max{|LCP(S_x,S_y)|+|LCS(S_x,S_y)|}(x\neq y)$$ (\(LCP/LCS\)分别表示最长公共前/后缀) \(1\leq n\leq 2\times 10^5\) 解题思路 正解好像是树上\(SA\)+线段树合并的做法可是我不会,就写了广义\(SAM\) \(S…
题意:给定字符串S,然后M个字符串T.Q次询问,每次给出(L,R,l,r),问S[l,r]在L到R这些T字符串中,在哪个串出现最多,以及次数. 思路:把所有串建立SAM,然后可以通过倍增走到[l,r]在SAM上的位置p,然后在这个位置p上求,求的过程就是一个线段树求区间最值. 现在的关键是得到线段树,这个线段树记录了endpos,这个可以用启发式合并. 注意现在是广义后缀自动机,不能用拓扑排序合并线段树. 必须用fail树DFS来合并. 不然会出错. 具体我也不知道,不过我估计是因为广义自动机里…
RemoteJudge 题目大意 给你一个串\(S\)以及一个字符串数组\(T[1...m]\),\(q\)次询问,每次问\(S\)的子串\(S[p_l...p_r]\)在\(T[l...r]\)中的哪个串里的出现次数最多,并输出出现次数. 如有多解输出最靠前的那一个. 思路 第一次见到在\(parent tree\)上线段树合并的题,感觉好妙 先对\(T\)建一个广义后缀自动机,考虑对\(SAM\)上的每一个结点建一颗线段树,值域为\([1,m]\),维护出现次数最多的串的位置和次数.又因为\…
原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L...R] 的最长前后缀. $$q,|S|\leq 2 \times 10 ^ 5$$ 题解 真是一道有趣的字符串题. 首先我们给 S 建出 SAM ,并用线段树合并预处理出每一个节点的 Right 集合. 我们要做的是找到最大的 $p$ 满足 $p<R, S[L...p] = S[R-p+L...R]…
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ395.html 题解 记得同步赛的时候这题我爆0了,最暴力的暴力都没调出来. 首先我们看看 68 分怎么做 ——求两个串的本质不同的公共子串个数. 它是一个模板题,然而我当时并不会,甚至连SAM都忘了怎么写QAQ. 再简化一下:如何求一个串的本质不同的子串个数. 给串建一个SAM,把所有节点代表的字符串个数(也就是 Max(x) - Max(fa(x)) 加起来就好了. 回到上一个问题. 假设这两个串分…
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任意一个点y,设节点y代表的最长串为S,设节点x代表的串为T1,T2,T3,...,设 F(S,T) 表示串T在S中的出现次数,则 F(S,T1) = F(S,T2) = F(S,T3) = ... 证明:假设串 Ta 和 Tb 在 S 中的出现次数不同,且 |Ta|+1=|Tb| 则必然存在一个位置…
题意:给你一个子串,m次询问,每次给你abcd,问你子串sa-b的所有子串和子串sc-d的最长公共前缀是多长 题解:首先要求两个子串的最长公共前缀就是把反过来插入变成最长公共后缀,两个节点在parent树上的lca就是最长公共后缀.找到某个子串就是在parent树上倍增 我们先二分答案,问题就变成了子串sx-y的所有子串中是否包含子串p,我们先倍增找到子串p,然后查询p在parent树上的子树是否包含子串sx-y的子串(parent树上的子树就是所有以p作为后缀的子串,如果sx-y的子串包含p,…
传送门 题意:给一个字符串SSS. 有mmm次询问,每次给四个参数a,b,c,da,b,c,da,b,c,d,问s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x...y]s[x...y]的最长公共前缀是多少. 思路:先翻转字符串转化为求最长公共后缀. 设现在求s[a...b]s[a...b]s[a...b]的所有子串和s[x...y]s[x...y]s[x...y]的最长公共后缀是多少. 然后二分答案,设最长公共后缀为s[y−mid+1...y]s[y-mid+…