zoukankan      html  css  js  c++  java
  • BZOJ 1030: [JSOI2007]文本生成器 [AC自动机 DP]

    1030: [JSOI2007]文本生成器

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 3953  Solved: 1614
    [Submit][Status][Discuss]

    Description

      JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,
    他们现在使用的是GW文本生成器v6版。该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文
    章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,
    那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的
    标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6
    生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?

    Input

      输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N (<= 60),GW文本生成器 v6生成的文本固
    定长度M;以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包
    含英文大写字母A..Z

    Output

      一个整数,表示可能的文章总数。只需要知道结果模10007的值。

    Sample Input

    2 2
    A
    B

    Sample Output

    100
     

    题意:求长度为m且含有至少一个模板串的字符串个数

    好神啊
    含有至少一个不好求,那就求不含模板串的然后总数减
    计数问题组合数学做不了就考虑DP
    f[i][j]表示长度为i匹配到自动机上节点j的不含模板串的方案数
    转移 f[i][j]-->f[i+1][t[j].ch[k]]
     
    如何判断一个串不含模板串?首先f[i][j]已经保证1..i-1是不含模板串的啦,只要保证第i个字符加入后也不含就行了
    ins时模板串终点打标记,本身且Fail祖先没有标记就说明AC自动机上j结尾的没有模板串
     
    但是有的字符模板串里没有啊?给root把孩子补全就行了【实际上不补全也是可以的,反正默认走到了根,最后f[m][根]也统计】
     
    思路和KMP一样,都是一边生成字符串一边在KMP/AC自动机上匹配,
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=105,M=6005,MOD=10007;
    int n,m;
    char s[N];
    struct node{
        int ch[26],fail,val;
    }t[M];
    int sz;
    void ins(char s[]){
        int u=0,n=strlen(s+1);
        for(int i=1;i<=n;i++){
            int c=s[i]-'A';
            if(!t[u].ch[c]) t[u].ch[c]=++sz;
            u=t[u].ch[c];
        }
        t[u].val=1;
    }
    int q[M],head,tail;
    void getAC(){
        head=tail=1;
        for(int i=0;i<26;i++){
            if(!t[0].ch[i]) t[0].ch[i]=++sz;
            q[tail++]=t[0].ch[i];
        }
        while(head!=tail){
            int u=q[head++];
            t[u].val|=t[t[u].fail].val;
            for(int i=0;i<26;i++){
                int &v=t[u].ch[i];
                if(!v) {v=t[t[u].fail].ch[i];continue;}
                t[v].fail=t[t[u].fail].ch[i];
                q[tail++]=v;
            }
        }
    }
    int f[N][M],ans;
    void dp(){
        f[0][0]=1;
        for(int i=1;i<=m;i++){
            for(int j=0;j<=sz;j++) if(!t[j].val&&f[i-1][j]!=0)
                for(int k=0;k<26;k++) if(!t[t[j].ch[k]].val)
                    f[i][t[j].ch[k]]=(f[i][t[j].ch[k]]+f[i-1][j])%MOD;
        }
        for(int j=0;j<=sz;j++) ans=(ans+f[m][j])%MOD;
    }
    int main(){
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);//printf("hi %d %d nm
    ",n,m);
        for(int i=1;i<=n;i++) scanf("%s",s+1),ins(s);
        getAC();
        dp();
        int tmp=1;
        for(int i=1;i<=m;i++) tmp=(tmp*26)%MOD;
        printf("%d",(tmp-ans+MOD)%MOD);
    }
     
     
     
     
     
  • 相关阅读:
    HDU2515_数学规律题
    HDU1086_You can Solve a Geometry Problem too_判断两线段相交
    HDU1115_Lifting the Stone_凹凸多边形重心_可作为模板
    HDU2036_改革春风照大地_点求多边形面积
    Codeforces Beta Round #92 (Div. 2 Only) _A题
    HDU2108_Shape of HDU_判断凹凸
    response.setContentType设置
    vue 文件下载实现
    iText5实现Java生成PDF文件完整版
    java使用IText将数据导出为pdf文件(数据为excel表格样式)
  • 原文地址:https://www.cnblogs.com/candy99/p/6220124.html
Copyright © 2011-2022 走看看