zoukankan      html  css  js  c++  java
  • bzoj1030: [JSOI2007]文本生成器

    mdzz调了一中午。。

    用了解的单词建AC自动机

    原问题显然不太好搞啊。。

    那么转换一下sum-不包含了解单词的文本数

    问题变成在AC机上走m步不到达ed节点的方案数

    变成DP: f[i][j]表示走到第i个节点,走了j步

    宽搜转移一下。

    坑点就是了解的单词有一个是另一个的字串就会减多

    这样的话要把fail全部跳一次

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int mod=10007;
    int MOD(int x){return (x%mod+mod)%mod;}
    
    struct Trie
    {
        int w[30],fail;
        bool ed;
        void clean(){memset(w,0,sizeof(w));fail=0;ed=false;}
    }tr[11000];int trlen;
    char ss[110];
    void maketree()
    {
        int now=0,len=strlen(ss+1);
        for(int i=1;i<=len;i++)
        {
            int x=ss[i]-'A'+1;
            if(tr[now].w[x]==0)
                tr[now].w[x]=++trlen, tr[trlen].clean();
            now=tr[now].w[x];
        }
        tr[now].ed=true;
    }
    
    int q[11000];
    void bfs()
    {
        int head=1,tail=2;q[1]=0;
        while(head!=tail)
        {
            int now=q[head];
            for(int x=1;x<=26;x++)
            {
                int son=tr[now].w[x];
                if(son!=0)
                {
                    if(now==0)tr[son].fail=0;
                    else
                    {
                        int p=tr[now].fail;
                        while(p!=0&&tr[p].w[x]==0)p=tr[p].fail;
                        tr[son].fail=tr[p].w[x];
                    }
                    q[tail]=son;
                    tail++;
                } 
            }
            head++;
        }
    }
    
    //-------------AC_machine--------------
    
    struct node
    {
        int now,uh;
    }list[1100000];
    bool v[11000][110];
    int f[11000][110];
    int main()
    {
        freopen("generator.in","r",stdin);
        freopen("generator.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",ss+1),maketree();
        bfs();
        
        memset(f,0,sizeof(f));f[0][0]=1;
        memset(v,false,sizeof(v));v[0][0]=true;
        int head=1,tail=2,ans=0;
        list[1].now=0;list[1].uh=0;
        while(head!=tail)
        {
            int now=list[head].now,uh=list[head].uh;head++;
            if(uh==m){ans=MOD(ans+f[now][uh]);continue;}
            for(int x=1;x<=26;x++)
            {
                int p=now;
                while(p!=0&&tr[p].w[x]==0)p=tr[p].fail;
                bool bk=true;
                int pp=tr[p].w[x];
                while(pp!=0)
                { 
                    if(tr[pp].ed==true){bk=false;break;}
                    pp=tr[pp].fail; 
                } 
                if(bk==true)
                {
                    if(tr[p].w[x]!=0)p=tr[p].w[x];
                    f[p][uh+1]=MOD(f[p][uh+1]+f[now][uh]);
                    if(v[p][uh+1]==false)
                    {
                        v[p][uh+1]=true;
                        list[tail].now=p;list[tail].uh=uh+1;
                        tail++; 
                    } 
                }
            }
        }
        int sum=1;
        for(int i=1;i<=m;i++)sum=MOD(sum*26);
        printf("%d
    ",MOD(sum-ans));
        return 0;
    }
  • 相关阅读:
    mybatis 动态sql
    linux shell 之 crontab(定时任务)详解
    FTP定时批量下载文件(SHELL脚本及使用方法 )
    腾讯云数据库团队:MySQL5.7 JSON实现简单介绍
    Chisel Tutorial(七)——模块
    大数问题解决模板
    可靠的功能測试--Espresso和Dagger2
    hdoj 1698 Just a Hook 【线段树 区间更新】
    平衡二叉树
    WPF中DependencyObject与DependencyProperty的源代码简单剖析
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8930432.html
Copyright © 2011-2022 走看看