absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] APIO练习赛第一题
[破碎的状态] 一道Flag网络流

[破碎的状态] BZOJ 2434 NOI2011 阿狸的打字机

absi2011 posted @ May 11, 2016 01:24:28 PM in 刷题记录 with tags 线段树 小高考 bzoj AC自动机 树链剖分 Trie , 532 阅读

这一题总算是过了..然而在某OJ上还是给70分可能是递归的栈爆炸了吧?

感谢@bx2k @billxu2000 提供解法思路

首先题面显著的告诉你:给你个trie

所以你把trie的fail指针求出来,这里面是AC自动机的求法

然后我们把询问给离线出来

然后..trie的fail是一颗树,我们可以把这颗树拿出来

每次我们询问对root到y的trie树路径上权值改为1其他为0的情况下,求x所在的fail树内的权值和即可

所以代码如下:

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[100005];
struct node
{
    int id;
    node * father;
    node * fail;
    node * ch[26];
    node ()
    {
        father=0;
        fail=0;
        memset(ch,0,sizeof(ch));
    }
};
node * b[100005];
node * root;
node * new_node()
{
    static node a[100005];
    static int top=0;
    return &a[top++];
}
struct edge
{
    int y;
    edge * next;
};
edge * li[100005];
edge * new_edge()
{
    static edge a[100005];
    static int top=0;
    return &a[top++];
}
void insert_edge(int x,int y)
{
    edge * t = new_edge();
    t->y=y;
    t->next=li[x];
    li[x]=t;
}
int dfn[100005];
int size[100005];
void dfs(int x)
{
    static int now=0;
    dfn[x]=now++;
    edge * t;
    size[x]=1;
    for (t=li[x];t!=0;t=t->next)
    {
        dfs(t->y);
        size[x]+=size[t->y];
    }
}
struct query
{
    int id;
    int x;
    int y;
    friend bool operator < (const query &a,const query &b)
    {
        return a.y<b.y;
    }
    void read()
    {
        scanf("%d%d",&x,&y);
        x--;
        y--;
    }
};
query c[100005];
int val[1<<18];
int querys(int num,int l,int r,int l0,int r0)
{
    if ((l0<=l)&&(r<=r0))
    {
        return val[num];
    }
    int mid=(l+r)/2;
    int sum=0;
    if (l0<mid) sum+=querys(num*2+1,l,mid,l0,r0);
    if (mid<r0) sum+=querys(num*2+2,mid,r,l0,r0);
    return sum;
}
void change(int num,int l,int r,int k,int t)
{
    if (l==r-1)
    {
        val[num]=t;
        return;
    }
    int mid=(l+r)/2;
    if (k<mid)
    {
        change(num*2+1,l,mid,k,t);
    }
    else
    {
        change(num*2+2,mid,r,k,t);
    }
    val[num]=val[num*2+1]+val[num*2+2];
}
int ans[100005];
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    scanf("%s",a);
    root=new_node();
    node * now=root;
    int i;
    int sum=0;
    for (i=0;a[i]!='\0';i++)
    {
        if (a[i]=='P')
        {
            b[sum++]=now;
        }
        else if (a[i]=='B')
        {
            now=now->father;
        }
        else
        {
            if (now->ch[a[i]-'a']==0)
            {
                now->ch[a[i]-'a']=new_node();
                now->ch[a[i]-'a']->father=now;
            }
            now=now->ch[a[i]-'a'];
        }
    }
    static node * que[100005];
    que[0]=root;
    int front=0,rail=1;
    root->fail=root;
    for (;front<rail;front++)
    {
        que[front]->id=front;
        int i;
        for (i=0;i<26;i++)
        {
            if (que[front]->ch[i]==0)
            {
                if (que[front]==root) que[front]->ch[i]=root;
                que[front]->ch[i]=que[front]->fail->ch[i];
                continue;
            }
            que[rail++]=que[front]->ch[i];
            if (que[front]==root)
            {
                que[front]->ch[i]->fail=root;
            }
            else
            {
                que[front]->ch[i]->fail=que[front]->fail->ch[i];
            }
        }
    }
    for (i=1;i<rail;i++)
    {
        insert_edge(que[i]->fail->id,i);
    }
    int n=rail;
    dfs(0);
    int m;
    scanf("%d",&m);
    for (i=0;i<m;i++)
    {
        c[i].read();
        c[i].id=i;
    }
    sort(c,c+m);
    c[m].y=-1;
    now=root;
    int x=0;
    sum=0;
    for (i=0;a[i]!='\0';i++)
    {
        if (a[i]=='P')
        {
            for (;c[x].y==sum;)
            {
                ans[c[x].id]=querys(0,0,n,dfn[b[c[x].x]->id],dfn[b[c[x].x]->id]+size[b[c[x].x]->id]);
                x++;
            }
            sum++;
        }
        else if (a[i]=='B')
        {
            change(0,0,n,dfn[now->id],0);
            now=now->father;
        }
        else
        {
            now=now->ch[a[i]-'a'];
            change(0,0,n,dfn[now->id],1);
        }
    }
    for (i=0;i<m;i++)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter