2434: [Noi2011]阿狸的打字机

标签: ac自动机
1人阅读 评论(0) 收藏 举报
分类:

首先容易根据给出的字符串建出trie树

对于查询(x,y),相当于对于y的每一个位置求出他的后缀是否包含x串

那么容易想到建立出ac自动机。

那么就是对于y串的每个位置,其能否通过fail到达x所在节点。

发现其实fail指针会构成一棵树,那么相当于统计在x节点下有多少点属于y串。

发现如果直接枚举是O(n2),那么考虑dfs trie树,记录每个位置是否是y串,

然后查询其对应x串下子树有多少节点是y串节点,然后这个东西容易发现可以直接通过dfs序用树状数组维护

此时复杂度为O(nlogn)

搞定.

c++代码如下:

#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define rep(i,x,y) for(register int i = x ;i <= y; ++ i)
#define repd(i,x,y) for(register int i = x ;i >= y; -- i) 
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
    x = 0;char c;int sign = 1;
    do { c = getchar(); if(c == '-') sign = 1; }while(!isdigit(c));
    do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
    x *= sign;
}

const int N = 1e5 + 50;
char s[N];
int n,sz = 1,cnt,p[N],fa[N],t[N][27];

inline void insert(char*s)
{
    n = strlen(s + 1);
    int x = 1;
    rep(i,1,n)
    {
        if(s[i] >= 'a' && s[i] <= 'z')
        {
            if(!t[x][s[i] - 'a'])
                t[x][s[i] - 'a'] = ++ sz,fa[sz] = x;
            x = t[x][s[i] - 'a'];
        }
        if(s[i] == 'B')
            x = fa[x];
        if(s[i] == 'P')
            p[++cnt] = x;
    }
}

int tot,head[N],nxt[N],to[N];
inline void add(int x,int y)
{
    to[tot] = y;
    nxt[tot] = head[x];
    head[x] = tot++;
}

int q[N],fail[N],st,en;
inline void build_ac()
{
    rep(i,0,25) t[0][i] = 1;
    q[st] = 1;
    while(st <= en)
    {
        int x = q[st++];
        rep(i,0,25)
            if(t[x][i]){
                int y = fail[x];
                while(!t[y][i]) y = fail[y];
                fail[t[x][i]] = t[y][i];
                add(t[y][i],t[x][i]);
                q[++ en] = t[x][i];
        }
    }
}

int m,ans[N];
int id[N],idx[N],size[N];

void dfs(int x)
{
    id[x] = ++ sz; size[x] = 1;
    for(register int i = head[x];~i;i = nxt[i])
        {
            dfs(to[i]);
            size[x] += size[to[i]];
        }
}

int T[N];
int Head[N],Nxt[N],Val[N],To[N],Tot;

inline void update(int x,int y)
{
    for(register int i = x; i <= n ;i += lowbit(i))
        T[i] += y;
}

inline int query(int x)
{
    int ans = 0;
    for(register int i = x ;i ; i -= lowbit(i))
        ans += T[i];
    return ans;
}

inline void Add(int x,int y,int w)
{
    To[Tot] = y;
    Nxt[Tot] = Head[x];
    Val[Tot] = w;
    Head[x] = Tot++;
}

void Dfs(int x)
{
    update(id[x],1);
    for(register int i = Head[x];~i;i = Nxt[i])
    {
        int y = To[i];
        ans[Val[i]] = query(id[y] + size[y] - 1) - query(id[y] - 1);
    }
    rep(i,0,25) if(t[x][i]) Dfs(t[x][i]);
    update(id[x],-1);
}

inline void solve()
{
    int x,y;
    memset(Head,-1,sizeof Head);
    read(m);
    rep(i,1,m)
    {
        read(x), read(y);
        Add(p[y],p[x],i);
    }
    sz = 0;dfs(1);
    Dfs(1);

    rep(i,1,m) printf("%d\n",ans[i]);

}

int main()
{
    memset(head,-1,sizeof head);
    scanf("%s",s + 1);
    insert(s);
    build_ac();
    solve();
    return 0;
}
查看评论

bzoj2434: [Noi2011]阿狸的打字机

传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2434 一个讲得很详细的题解:http://blog.csdn.net/huzeco...
  • thy_asdf
  • thy_asdf
  • 2015-07-26 17:50:36
  • 1387

NOI2011 阿狸的打字机(BZOJ2434) 题解

Link 原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2434       Description 阿狸喜欢收藏各种稀奇古怪的...
  • huzecong
  • huzecong
  • 2012-07-21 11:52:29
  • 3106

[BZOJ2434][NOI2011]阿狸的打字机(AC自动机+树状数组)

有希望在的地方,痛苦也成欢乐。
  • Clove_unique
  • Clove_unique
  • 2016-04-04 23:11:54
  • 903

bzoj2434【NOI2011】阿狸的打字机

AC自动机+树状数组+DFS序
  • AaronGZK
  • AaronGZK
  • 2016-05-25 00:14:28
  • 2719

[NOI2011]阿狸的打字机(AC自动机+树状数组)

【题解】 KMP算法:每次询问时求出x串的失配函数,然后在y串上匹配,总复杂度O(m*len) 可以得40分  如果把所有单词建成一棵字母树,考虑类似的暴力: 对每次询问,枚举y串的每个点(将这个点...
  • cjk_cjk
  • cjk_cjk
  • 2015-03-16 00:57:03
  • 662

[NOI2011][JZOJ2784]阿狸的打字机

题目描述有一个缓存槽,设计一个程序维护下面三个操作: ∙insert c\bullet insert\ c:在缓存槽末尾插入小写字符cc ∙print\bullet print:将缓存所有字符连接...
  • a_crazy_czy
  • a_crazy_czy
  • 2016-01-27 19:21:35
  • 616

【NOI2011】bzoj2434 阿狸的打字机

AC自动机+dfs序+树状数组
  • sdfzyhx
  • sdfzyhx
  • 2017-04-20 21:30:51
  • 234

[Noi2011]阿狸的打字机

这道题由于读入的字符串长度可能很大,不能一个一个字符串插入trie图。 又因为一个字符串形成以后字母不会消失,于是便可以一边读入一边建trie图。 然后,由于fail指针指向最长后缀,就可以将fail...
  • u012602144
  • u012602144
  • 2014-02-19 14:17:36
  • 667

bzoj2434 阿狸的打字机 AC自动机&&树状数组

做完CTSC的题再去做NOI的题。。发现还是不会ww~/(ㄒoㄒ)/~~虽然是常规思路。     首先你会发现他打字的方式非常奇妙。。实际上不就是在构建一颗Tire吗?P相当于给节点标记;B相当于退回...
  • lych_cys
  • lych_cys
  • 2016-02-09 15:29:10
  • 1310

bzoj2434: [Noi2011]阿狸的打字机 trie+线段树

我们可以先按题目描述建出一个trie树,然后得到fall树,我们可以发现,fall树的子树里有#include #include #include #include using namespa...
  • IED98
  • IED98
  • 2015-07-13 10:55:01
  • 377
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 1999
    积分: 775
    排名: 6万+
    博客专栏
    文章分类
    文章存档