God Only Knows! AC自动机
The 11th UESTC Programming Contest Final
My Solution
题意:给一个字符串s,然后给出n个字符串stri,问s的不包含任意stri串的子串的个数。
做了一晚上,终于用自己的方法过了,开心 Y ^ _ ^ Y。
先用给出的n个串stri来建立AC自动机,其中在朴素AC自动机的基础上添加一个depth[MAX_SIZE]成员用来记录每个节点的深度。
然后根据主串s在自动机上跑,碰到危险节点(即danger节点, 给定串stri的结尾节点是危险节点或者该节点的后缀节点是危险节点的节点)时,
维护lastdanger 表示主串s已经出现过的stri中最靠近i的危险串在主串上的起点(即给定串的某个起点),这个可以先遇到危险节点,
然后用该节点的深度ac.depth[now]来求出该危险串的起点,然后维护lastdanger。
且当前节点是危险节点时,用fail指针访问该节点的后缀节点,如果新的节点还是危险节点则继续维护lastdanger,并继续访问当前节点的后缀节点,
直到访问到非danger节点时,才继续在自动机上遍历主串的下一个字符。
if(ac.danger[now]){
while(ac.danger[now]){
lastdanger = max(lastdanger, i - ac.depth[now] + 1);
now = ac.fail[now];
}
}
在主串中没访问一个字符时ans += (LL)(i - lastdanger);//lastdanger 初始化为-1
比如
abcdefg
0123456//这个是上面字符串的下标
2
bcd
ef
当访问012时没有碰到危险节点,当遍历到3即d时,碰到了危险节点这是要更新lastdanger为1,然后遍历到5即f时又要更新lastdanger,
ans = 0 - (-1), + 1 - (-1), + 2 - (-1), + 3 - 1, + 4 - 1, + 5 - 4, + 6 - 4 == 14;
复杂度 O(T*n)
#include
#include
#include
#include
#include
#include
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
https://www.prolightsfxjh.com/
Thank you!
------from ProLightsfx
共有 0 条评论