柱爷搞子串 题目连接:
()
Description
柱爷有一个字符串S,对于其中的每一个不同子串\(S^\ast\),柱爷都能O(1)
的得到这些字符串的所有匹配位置
即能知道所有的[L,R]
区间使得
\(S[L,R]=S^\ast\),然后柱爷会把这些[L,R]区间的每个位置做上标记,如果最后这些标记位置形成了K个连通块,那么它对答案的贡献就是1
柱爷早就知道了答案,但他现在想问你知道吗?
输入第一行一个字符串S,只有小写字母,保证\(|S|≤10^5\)
接下来一行一个K
,保证
\(1≤K≤|S|\) Output
输出一行表示答案
abaab
2
Sample Output
3
Hint
对于ababa的字串aba它对所有字符都打上了标记,所以只有1个联通块
题意
对于每一个不同字串,对他的每一个出现位置的每一个字符都打上标记,形成k个联通块答案加1。
题解:
换个角度,如果我们知道了sam后缀自动机里面每个节点的right集,对于每一个right集,我们就可以知道一个字串长度区间使这个集合形成k个联通块,再和这个节点的接受长度区间取个交就是这个节点的所有可行解。
串长度有1e5,对于全是a数据,他的right集和的个数达到1e10,显然暴力出right集是不行的。
那么我们可以用set的维护right集,用平衡树维护right的差分数组,维护出来后对于差分数组我们只要求第size-k的大小就可以算得贡献。最后用启发式合并一下,虽然总体是nloglog,但在后缀树上的启发式跑得很快。
如果是随机数据,那么直接用set爆出right集应该也是没有问题的。
代码
//#include #include #include #include #include #include #include #include #include #include #include #include