zoukankan      html  css  js  c++  java
  • Bzoj 3172: [Tjoi2013]单词(fail树)

    3172: [Tjoi2013]单词
    Time Limit: 10 Sec Memory Limit: 512 MB
    Description
    某人读论文,一篇论文是由许多单词组成。但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文中出现多少次。
    Input
    第一个一个整数N,表示有多少个单词,接下来N行每行一个单词。每个单词由小写字母组成,N<=200,单词长度不超过10^6
    Output
    输出N个整数,第i行的数字表示第i个单词在文章中出现了多少次。
    Sample Input
    3
    a
    aa
    aaa
    Sample Output
    6
    3
    1

    /*
    fail树.
    一开始没想出用AC自动机怎么做.
    原来是fail树处理.
    因为fail指针有一个很好的性质
    就是某个字串的后缀等于fail指向位置的前缀.
    那么显然的p的深度 > p->fail .
    我们bfs的时候有一个已经处理好的深度关系.
    那么我们倒序相加把贡献转移给文章中给定的前缀串就好了.
    那么某个字符串答案的贡献就来源于两部分.
    case 1:与该串前缀相同的字串个数.
    case 2:与该串前缀不同的字串个数.
    对于case 1,我们可以在建trie的时候直接算出来.
        case 2 我们统一把贡献转移给前缀串. 
    */
    #include<cstring>
    #include<cstdio>
    #define MAXN 1000010
    using namespace std;
    int n,m,tot=1,l,fail[MAXN],ans[MAXN],p[201],q[MAXN];
    char s[MAXN];
    struct data{int x[27],b;}tree[MAXN];
    void add(int t)
    {
        l=strlen(s+1);int now=1;
        for(int i=1;i<=l;i++)
        {
            int x=s[i]-96;
            if(!tree[now].x[x]) tree[now].x[x]=++tot;
            now=tree[now].x[x];
            ans[now]++;
        }
        tree[now].b++;p[t]=now;
        return ;
    }
    void Build_fail()
    {
        for(int i=1;i<=26;i++) tree[0].x[i]=1;
        int now=1,head=0,tail=0;
        q[++tail]=1;
        while(head<tail)
        {
            int now=q[++head];
            for(int i=1;i<=26;i++)
            {
                if(!tree[now].x[i]) continue;
                int k=fail[now];
                while(!tree[k].x[i]) k=fail[k];
                k=tree[k].x[i];
                fail[tree[now].x[i]]=k;
                q[++tail]=tree[now].x[i];
            }
        }
        for(int i=tail;i>=1;i--) ans[fail[q[i]]]+=ans[q[i]];
        return ;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%s",s+1),add(i);
        Build_fail();
        for(int i=1;i<=n;i++) printf("%d
    ",ans[p[i]]);
        return 0;
    }
  • 相关阅读:
    快乐的深圳之旅
    编码和字体[zz]
    USB转串口芯片几点总结有疑问
    ANSI/UTF8/UCS2(UTF16),以及回车换行[zz]
    详细介绍四线电阻触摸屏的工作原理[zz]
    无字库12864液晶的驱动方法[zz]
    字符集和字符编码(Charset & Encoding)[zz]
    搭建CodeBlocks+wxWidgets可视化编程环境(Windows)
    wxWidgets初始化分析应用定义和初始化
    开发CodeBlocks插件(1)入门篇
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068034.html
Copyright © 2011-2022 走看看