P2336 [SCOI2012]喵星球上的点名(AC 自动机 + BIT + dfn 序 + LCA )
这道题除了 AC 自动机中 Fail 树本身的性质,与其他题目最大不同是它 AC 自动机的建立。
这道题的字符集特别大,所以我们不能和以前一样直接存下来,于是可以想到用 Map 维护每个点可以到达的点集。
其他的区别不大,有三个地方要注意:
(1.) 对于一个喵星人,既有名又有姓,怎么统计呢?
直接把两个拼在一起然后搞一个间隔符就可以了。
(2.) 题目第一问要求不重复,于是和之前那道题一样,删除贡献即可。
(3.) Fail 树的构建(暂时不知道复杂度)
for(register mit it=t[0].son.begin();it!=t[0].son.end();it++) q[++r]=it->second,fail(it->second)=0;
while(l<=r){
int now=q[l];l++;
for(register mit it=t[now].son.begin();it!=t[now].son.end();it++){
int Fail=fail(now),val=it->first;
while(Fail and !son(Fail,val)) Fail=fail(Fail);
fail(it->second)=son(Fail,val);
q[++r]=it->second;
}
}
for(register int i=1;i<=node_cnt;i++) Add_Edge(fail(i),i);
然后这道题第一问就是让我们统计子树和,单点修改,第二问和上一题几乎一样,单点子树修改,然后单点查询即可。
最后这篇题解讲的不错,还看不懂可以看这个。