[BZOJ3881][Coci2015]Divljak(AC自动机+dfs序+lca+bit)

本文介绍了如何使用AC自动机解决Divljak问题,通过将所有S串加入Trie树,并构建fail树。在匹配过程中,对每个匹配点,找到其在fail树到根的路径上的end标记S串进行计数,并通过dfs序和LCA消除重复计算。最后,利用bit数据结构处理单点修改和区间查询。
摘要由CSDN通过智能技术生成

题目描述

传送门

题解

首先把所有的S串都丢到trie树里,建立fail树。
每加进来一个T,把它在AC自动机上暴力匹配,匹配到的每一个点在fail树中到根的路径上出现过的S串end标记的S串都应该+1,也就是说,每一次求出匹配到的每一个点在fail树中到根的路径上出现过的end标记表示的S串,然后取并集,这些S串的答案应该+1.
由于有可能有重复计算,我们需要把所有匹配过的点按照dfs序排序,然后要消除相邻的两个点的lca到根的路径上多加的点的影响。如果是树链修改的话比较麻烦,可以转化为单点修改然后查询子树区间权值和,这样就可以用bit轻松实现了。

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define S 2000005
#define N 100005
#define lg 21

char s[S];
int n,m,opt,x,sz,dfs_clock;
int ch[S][30],fail[S],is_end[N],f[S][lg+1],in[S],out[S],h[S],pt[S],C[S];
int tot,point[S],nxt[S],v[S];
queue <int> q;

void insert(int id)
{
    int len=strlen(s),now=0;
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值