[SAM][dp][拓扑排序][模板] 洛谷 P3975 TJOI2015 弦论

题目链接

题意:

给定一个长度为 n 的字符串,让求出它的第 $k$ 小子串是什么。每次除字符串之外还会给定两个参数 $t $和 $k$ ,$t$ 为 $0$ 则表示不同位置的相同子串算作一个, $t$ 为 $1$ 则表示不同位置的相同子串算作多个。数据范围 $n\le 5*10^5$ $t\in {0,1}$ , $k \le 10^9$.

题解:

后缀自动机板子题。我们知道每一个子串放在sam上跑一定可以走到一个合法节点,反过来说任意一个节点一定代表了一批能走到这儿的子串。那么我们可以想办法把到达每个节点有多少种子串用dag图上dp的方式求出来,然后在t=1的时候,根据sam的性质,给每个dp值再乘以一个 $|endpos|$ 就可以了。学习到的是比我原来板子更快的拓扑排序方式。。。直接用len结果在数组里排序,比起用queue来常数小了很多。另外还纠正了自己的对于sam拓扑序的一个错误认识,他其实无论是slink还是dwag的拓扑序都是一样的,因为无论哪种都一定是从小的子串往大的走。
继续阅读“[SAM][dp][拓扑排序][模板] 洛谷 P3975 TJOI2015 弦论”

[AC自动机][字符串][模板][优化] HDU3695 Computer Virus on Planet Pandora

https://cn.vjudge.net/problem/HDU-3695

跟2222几乎一样,求文本中出现了多少个模式串,但是数据量变大了,5e6的长度。这时候用原来的写法已经会tle了,看到别人说用打标记的方式记录trie上一个节点有没有走过,一开始是不理解的,为什么这么做是正确的?后来想了想,AC自动机的算法确定了一个起点之后,沿着fail回溯的路径便已经确定(神奇),所以这条路上被走过的单词尾,再走的时候就会重复,而我们可以简单的把走过的节点计数标志变为-1,而在之后的过程中再遇到就可以不用管这个节点及其之后所有的节点了。注意这个是在while一开始就得判断。

WA的话,是从带括号的那个原串解压过后忘了在最后加’\0’。。。emmmm以后试验这种一定要从大到小试验数据。还有就是模板一定要用自己熟悉的。。原来以为这题问题在于kuangbin的板子不够快后来发现是没标记。。第二个是一开始没意识到q可以不止1位。。

继续阅读“[AC自动机][字符串][模板][优化] HDU3695 Computer Virus on Planet Pandora”