【Codeforces】547E. Mike and Friends-AC自动机

传送门:cf547E


题解

AC自动机+主席树


代码

#include<bits/stdc++.h>
#define mid ((l+r)>>1)
#define lc k<<1
#define rc k<<1|1
#define pb push_back
using namespace std;
typedef long long ll;
const int N=2e5+10;

int n,m,ed[N],fl[N],ch[N][26],df[N],ot[N],dfn,cnt;
int rt[N],ls[N*25],rs[N*25],cot;ll ss[N*25];
string s[N];vector<int>g[N];

inline void ins(int id)
{
	int i,u=0,alp,len;
	cin>>s[id];len=s[id].size();
	for(i=0;i<len;++i){
		alp=s[id][i]-'a';
	    if(!ch[u][alp]) ch[u][alp]=++cnt;
	    u=ch[u][alp];
	}
	ed[id]=u;
}

queue<int>que;
inline void bfs()
{
	int i,u,x,y,z;
	for(i=0;i<26;++i) if(ch[0][i]) que.push(ch[0][i]);
	for(;!que.empty();){
		x=que.front();que.pop();y=fl[x];
		for(i=0;i<26;++i){
			u=ch[y][i];z=ch[x][i];
			if(!z) ch[x][i]=u;
			else{fl[z]=u;que.push(z);}
		}
	}
	for(i=1;i<=cnt;++i) g[fl[i]].pb(i);
}

void ad(int pre,int &k,int l,int r,int pos)
{
	if(k==pre){k=++cot;ls[k]=ls[pre];rs[k]=rs[pre];ss[k]=ss[pre];}
    ss[k]++;if(l^r){
    	if(pos<=mid) ad(ls[pre],ls[k],l,mid,pos);
    	else ad(rs[pre],rs[k],mid+1,r,pos);
    }
}

void dfs(int x)
{df[x]=++dfn;for(int u:g[x]) dfs(u);ot[x]=dfn;}

inline void build(int pre,int &nw,int id)
{
	int i,u=0,len=s[id].size();nw=pre;
	for(i=0;i<len;++i){
		u=ch[u][s[id][i]-'a'];
		if(u) ad(pre,nw,1,dfn,df[u]);
	}
}

ll ask(int pre,int k,int l,int r,int L,int R)
{
	if((!k) || (ss[k]==ss[pre])) return 0;
	if(L<=l && r<=R) return ss[k]-ss[pre];
	if(R<=mid) return ask(ls[pre],ls[k],l,mid,L,R);
	if(L>mid) return ask(rs[pre],rs[k],mid+1,r,L,R);
	return ask(ls[pre],ls[k],l,mid,L,R)+ask(rs[pre],rs[k],mid+1,r,L,R);
}

int main(){
	int i,x,y,z;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i) ins(i);
	bfs();dfs(0);
	for(i=1;i<=n;++i) build(rt[i-1],rt[i],i);
	for(;m;--m){
		scanf("%d%d%d",&x,&y,&z);
		printf("%I64d\n",ask(rt[x-1],rt[y],1,dfn,df[ed[z]],ot[ed[z]]));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值