zoukankan      html  css  js  c++  java
  • 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
    ",ans[i]);
    } 
    

      

  • 相关阅读:
    PHP post方式请求webservice接口以及解析返回的数据
    XYTipsWindow弹出层
    php使用rtrim时,可能会出现乱码
    带搜索的下拉框
    js实现自动给省市县地区自动赋值
    php 获取指定日期段内每一天的日期
    sqlserver数据库的备份和还原
    js判断哪个单选框应该被选中
    extjs3.1 解决列锁定,合计行不能滑动的问题
    考研数据结构-二叉树
  • 原文地址:https://www.cnblogs.com/fzmh/p/5288393.html
Copyright © 2011-2022 走看看