• [BZOJ1030] [JSOI2007]文本生成器


    1030: [JSOI2007]文本生成器

    Time Limit: 1 Sec  Memory Limit: 162 MB

    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
     
    AC自动机模板题
    设计在AC自动机上的dp,设f[i][j]表示第i位在AC自动机上的第j个位置的方案数。
    转移为f[i][ch[j][k]]=f[i][ch[j][k]]+f[i-1][j]
    注意处理单词结尾的节点。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<cstring>
     7 #include<queue>
     8 using namespace std;
     9 int n,m;
    10 int ans2,ans1=1;
    11 struct data
    12 {
    13     int sz,ch[6005][30],val[6005],fail[6005],last[6005];
    14     int f[105][6005];
    15     void build(char *a)
    16     {
    17         int len=strlen(a);
    18         int now=0;
    19         for(int i=0;i<len;i++)
    20         {
    21             int to=a[i]-'A';
    22             if(!ch[now][to]) ch[now][to]=++sz;
    23             now=ch[now][to];
    24         }
    25         val[now]=1;
    26     }
    27     void getfail()
    28     {
    29         queue<int> q;
    30         for(int i=0;i<26;i++)
    31         {
    32             if(ch[0][i])
    33             {
    34                 int to=ch[0][i];
    35                 last[to]=val[to];
    36                 q.push(to);
    37             }
    38         }
    39         while(!q.empty())
    40         {
    41             int now=q.front();q.pop();
    42             for(int i=0;i<26;i++)
    43             {
    44                 int u=ch[now][i];
    45                 if(!ch[now][i]){ch[now][i]=ch[fail[now]][i];continue;}
    46                 int t=fail[now];
    47                 while(t&&!ch[t][i]) t=fail[t];
    48                 fail[u]=ch[t][i];
    49                 if(val[u]) last[u]=1;
    50                 last[u]+=last[fail[u]];
    51                 q.push(u);
    52             }
    53         }
    54     }               
    55     void dp()
    56     {
    57         f[0][0]=1;
    58         for(int i=1;i<=m;i++)
    59         {
    60             for(int j=0;j<=sz;j++)
    61             {
    62                 if(last[j]) continue;
    63                 for(int k=0;k<26;k++)
    64                 {
    65                     f[i][ch[j][k]]=(f[i][ch[j][k]]+f[i-1][j])%10007;
    66                 }
    67             }
    68         }
    69         for(int i=0;i<=sz;i++){if(!last[i]){ans2=(ans2+f[m][i])%10007;}}
    70         for(int i=1;i<=m;i++) ans1=(ans1*26)%10007;
    71         printf("%d",((ans1-ans2)%10007+10007)%10007);
    72     }
    73 }t;
    74 int main()
    75 {
    76     scanf("%d%d",&n,&m);
    77     char s[6000];
    78     for(int i=1;i<=n;i++) scanf("%s",s),t.build(s);
    79     t.getfail();t.dp();
    80     return 0;
    81 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    linux-log-files/
    SSL SSH
    C++学习的书籍
    Linux IO 分析
    LINUX 常用操作
    Find Large Files in Linux
    Linux 常见操作
    Linux Performance tool
    /linux-command-line-bash-shortcut-keys/
    Sed
  • 原文地址:https://www.cnblogs.com/wls001/p/7307328.html
Copyright © 2020-2023  润新知