你以为我只是单纯的子序列自动机吗?其实我是是子序列自动机+可持久化数组哒!
但是我看见一个大神给出了一个特别神仙又巧妙的思路!我不禁要写一篇题解记录下这神奇的思路!
而且代码贼短哦~比可持久化数组好写到不知道多少倍呢www
题意简述
给定一个序列 A A A长度<=1e5,还要一些要询问的字符串 B B B,长度和 < = 1 e 6 <=1e6 <=1e6。对于每个 B B B,询问其是否是 A A A的子序列。序列中的每个值都在 1 e 5 1e5 1e5以内。
思路框架
在暴力匹配子序列的时候,用链表(或者vector)记录哪些询问的答案会被更新即珂。复杂度 O ( 1 e 6 + 1 e 5 ) O(1e6+1e5) O(1e6+1e5)。
具体思路
这个思路是洛谷上一个叫“丁文涛2004”的神仙写的一个“链式前向星-子序列自动机”。非常强大。借这篇文章膜一下这个巨佬。
正片开始。我们知道,朴素的子序列的查询是 O ( ∣ A ∣ × ∣ B ∣ ) O(|A|\times |B|) O(∣A∣×∣B∣)的。我们大约是这样写的:
int p=1;
F(i,1,|A|) if (A[i]==B[p]) ++p;
然后判断是否p==|B|。其中 p p p表示我们当前匹配到了哪一个位置。
子序列自动机:设 n x t [ i ] [ j ] nxt[i][j] nxt[i][j]表示 i i i往后第一个值为 j j j的出现在哪一个位置。这样的确方便查询,但是这里值域