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

    题目描述

    JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版。

    该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文章—— 也就是说,生成的文章中每个字节都是完全随机的。如果一篇文章中至少包含使用者们了解的一个单词,那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。但是,即使按照这样的标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?。ZYX需要指出GW文本生成器 v6

    生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助吗?

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    2 2
    A
    B
    
    输出样例#1: 复制
    100
    令f[i][j]表示文章长度为i,在AC自动机位置为j没有单词的方案数
    然后答案就是26m-∑f[m][]
    转移就是从AC自动机往下走
    f[i+1][ch[j][k]]+=f[i][j] (ch[j][k]位置没有标记)
    注意处理AC自动机时,处理包含的情况
    val[x]|=val[fail[x]]
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 queue<int>Q;
     9 int ch[10010][27],f[110][10010],size,val[10010],fail[10010],n,m,Mod=10007,ans;
    10 char s[110];
    11 int qpow(int x,int y)
    12 {
    13   int res=1;
    14   while (y)
    15     {
    16       if (y&1) res=1ll*res*x%Mod;
    17       x=1ll*x*x%Mod;
    18       y>>=1;
    19     }
    20   return res;
    21 }
    22 void insert(int len)
    23 {int i;
    24   int now=0;
    25   for (i=0;i<len;i++)
    26     {
    27       if (ch[now][s[i]-'A']==0)
    28     ch[now][s[i]-'A']=++size;
    29       now=ch[now][s[i]-'A'];
    30     }
    31   val[now]=1;
    32 }
    33 void AC_build()
    34 {int i;
    35   for (i=0;i<26;i++)
    36     if (ch[0][i])
    37       fail[ch[0][i]]=0,Q.push(ch[0][i]);
    38   while (Q.empty()==0)
    39     {
    40       int u=Q.front();
    41       Q.pop();
    42       for (i=0;i<26;i++)
    43     {
    44       if (ch[u][i]) fail[ch[u][i]]=ch[fail[u]][i],Q.push(ch[u][i]);
    45       else ch[u][i]=ch[fail[u]][i];
    46       if (val[fail[u]])
    47         val[u]=val[fail[u]];
    48     }
    49     }
    50 }
    51 int main()
    52 {int i,j,k,len;
    53   cin>>n>>m;
    54   for (i=1;i<=n;i++)
    55     {
    56       scanf("%s",s);
    57       len=strlen(s);
    58       insert(len);
    59     }
    60   AC_build();
    61   f[0][0]=1;
    62   for (i=0;i<m;i++)
    63     {
    64       for (j=0;j<=size;j++)
    65     if (f[i][j]&&val[j]==0)
    66     {
    67       for (k=0;k<26;k++)
    68         {
    69           f[i+1][ch[j][k]]+=f[i][j];
    70           if (f[i+1][ch[j][k]]>=Mod) f[i+1][ch[j][k]]-=Mod;
    71         }
    72     }
    73     }
    74   for (i=0;i<=size;i++)
    75     if (val[i]==0)
    76     {
    77       ans+=f[m][i];
    78       if (ans>=Mod) ans-=Mod;
    79     }
    80   cout<<(qpow(26,m)-ans+Mod)%Mod;
    81 }
  • 相关阅读:
    简单线程池的设计
    MFC开发--截图工具
    Win32小游戏--蜘蛛纸牌
    C++语言动态创建对象
    C++语言类之间的关系
    c++语言虚函数实现多态的原理(更新版)
    5-24 c++语言之【基础知识】
    小细节--关于printf的输出问题
    Win32小游戏--贪吃蛇
    2020北大夏令营 终末游记
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8444553.html
Copyright © 2011-2022 走看看