题目大意
现在有N个单词,Q次询问,每次询问包含两个字符串a和b,求出以a为前缀且以b为后缀的单词共有多少个,其中a和b不互相覆盖。
解题思路
题目中所说的a和b不互相覆盖的含义是当 a =“ac”b = “cm”时,“acm”串不满足条件,因为其以a为前缀且以b为后缀时,a和b相互覆盖了。
题解中所说的做法没太看懂,现在给出一种巧妙构造并利用AC自动机解题的方法。
由于询问的时候,每次给出两个字符串并不便于操作,不妨将后缀与前缀拼接在一起,并使用特殊的符号进行标记。将所有询问离线,建立AC自动机。并将给出的N个单词拼在一起,具体操作为:
1.将每个单词复制一份拼接在原单词后面,中间使用一种分隔符连接,此分隔符与询问中的区分前后缀的分隔符相同,构成新的单词。
2.将新的单词依次连接起来,中间使用另一种分隔符连接,将所有单词连接成一篇文章。
3.原问题转化为,求出一篇文章中的存在的每种模式串的数量,是经典的AC自动机求解问题。
为了方便理解,此处以样例作为栗子
Sample Input
**1
4 4
aba
cde
acdefa
cdef
a a
cd ef
ac a
ce f**
将给出的单词拼接成文章为:
aba|aba#cde|cde#acdefa|acdefa#cdef|cdef#
将前后缀处理为新的字符串:
S1=“a|a”,S2=”ef|cd”,S3=“a|ac”,S4 = “f|ce”
将S1-S4依次insert,建成AC自动机,离线询问
扫描文章,对于每次询问依次回答即可
小Tips:由于题目中给出了前后缀不能覆盖的条件,所以扫描文章的时候需要加入特判。
附上代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxnode 2005000
#define sigma 30
using namespace