第一道AC自动机题目。
记一下对AC自动机的理解吧:
AC自动机=Trie+KMP。即在Trie上应用KMP思想,实现多Pattern的匹配问题。
复杂度是预处理O(segma len(P)),匹配是O(len(T))。应该也是下界了。
它预处理做了以下事情:
1、建立所有Pattern的Trie
2、计算出fail和last数组
匹配时和KMP很像。
我对fail和last的理解:
对于一棵Trie,上面的一个节点对应一个字符串,该字符串是root到该节点的路径上,边代表的字符连接起来的。
fail[i]是一个指针,它指向一个节点f,使得f代表的字符串是i代表的字符串最长的一个后缀(所以f的深度一定比i小)。
last[i]也是一个指针,它指向一个节点f,使得f代表的字符串是i代表的字符串的一个后缀且该后缀也是一个Pattern。(如果不存在则指向根)。
我们将根节点代表的字符串理解成空串,空串是任何字符串的子串。
对于匹配过程,我们将Text串也想成一个由点和边组成的链,我们从最左边的点开始向右开始匹配。
我们以Text串的位置为阶段进行匹配,如果Trie的当前节点存在一条边,使得它代表的字符串和text串一致,就两边都前进。如果不存在,trie中的节点就不断通过fail向上跳,直到存在边或到达根,如果存在边就同时向下走,否则(即到达根且根也没有对应边),那就trie保持在根,text串到下一节点。
然后每到一个新的trie节点就查看是否匹配到(要用到last数组).
去重的几种方式:
1、set
2、sort+unique
3、mark+vector
各有特点,
set是实时添加和查询,O(nlogn)。
sort+unique是添加完后查询(多用于离散话),也是O(nlogn)(常数比前者小)。
mark+vector,要求范围较小(10^7以内),O(n)
1 /**************************************************************
2 Problem: 2754
3 User: idy002
4 Language: C++
5 Result: Accepted
6 Time:1320 ms
7 Memory:13264 kb
8 ****************************************************************/
9
10 #include
11 #include
12 #include
13 #include
14 #include <set>
15 #include
View Code