• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
XD-TEST
博客园    首页    新随笔    联系   管理    订阅  订阅

BZOJ2434 [Noi2011]阿狸的打字机

  AC自动机+树状数组

  先建出fail树,对于查询x在y中出现几次,就等于在x为根的子树下有多少个节点为单词y在tire树路径上所在的节点,可用dfs+树状数组离线求出答案。

#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<vector>
#define pb push_back 
#define mp make_pair 
#define fi first
#define sc second
#define N 1000010
using namespace std;
char s[N];
int tmp,len,i,fa[N],cnt,p[N],tot,fail[N],c,a,b,ans[N];
int C[N];
int f[N][27],ss,L[N],R[N],m;
int dp,pre[N],tt[N],query[N];
queue<int> q;
vector<pair<int,int> > vec[N];
int lowbit(int x)
{
	return x&(-x);
}
void cc(int x,int w)
{
	while (x<=ss)
	{
		C[x]+=w;
		x+=lowbit(x);
	}
}
int sum(int x)
{
	int ans=0;
	while (x>0)
	{
		ans+=C[x];
		x-=lowbit(x);
	}
	return ans;
}
void link(int x,int y)
{
	dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
}
void dfs(int x)
{
	int i=p[x];
	ss++;L[x]=ss;
	while (i)
	{
		dfs(tt[i]);
		i=pre[i];
	}
	R[x]=ss;
}
void solve()
{
	int i,tmp=0,cnt=0,j;
	for (i=0;i<len;i++)
	if (s[i]=='B')
	{
		cc(L[tmp],-1);
		tmp=fa[tmp];
	}
	else
	if (s[i]=='P')
	{
		cnt++;
		for (j=0;j<vec[cnt].size();j++)
		{
			int o=query[vec[cnt][j].fi];
			ans[vec[cnt][j].sc]=sum(R[o])-sum(L[o]-1);
		}
	}
	else
	{
		tmp=f[tmp][s[i]-97];
		cc(L[tmp],1);
	}
}
int main()
{
	scanf("%s",s);
	len=strlen(s);
	tmp=0;
	for (i=0;i<len;i++)
	if (s[i]=='B')
	tmp=fa[tmp];
	else
	if (s[i]=='P')
	{
		cnt++;
		query[cnt]=tmp;
	}
	else
	{
		if (f[tmp][s[i]-97]==0)
		{
			f[tmp][s[i]-97]=++tot;
			fa[tot]=tmp;
		}
		tmp=f[tmp][s[i]-97];
	}
	
	for (i=0;i<26;i++)
	if (f[0][i])
	{
		fail[f[0][i]]=0;
		q.push(f[0][i]);
	}
	while (!q.empty())
	{
		c=q.front();q.pop();
		for (i=0;i<26;i++)
		if (f[c][i]==0)
			f[c][i]=f[fail[c]][i];
		else
		{
			fail[f[c][i]]=f[fail[c]][i];
			q.push(f[c][i]);
		}
	}
	
	for (i=1;i<=tot;i++)
	link(fail[i],i);
	dfs(0);
	scanf("%d",&m);
	for (i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		vec[b].pb(mp(a,i));
	}
	solve(); 
	for (i=1;i<=m;i++)
	printf("%d\n",ans[i]);
} 

  

posted @ 2016-03-17 17:49  fzmh  阅读(210)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3