zoukankan      html  css  js  c++  java
  • 【BZOJ1030】【JSOI2007】文本生成器

    我现在连AC自动姬都不会,怎么办嘛QAQ

    原题:

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

    N <= 60,所有单词及文本的长度不会超过100

    如果一个串的后缀不能选,这个串当然也不能选

    延伸到AC自动姬上就是如果一个串fail指向的节点不能选,这个节点就不能选

    然后就可以预处理出那些节点不能选

    然后用f[i][j]表示在文本串走到i时AC自动姬上走到j节点的方案数

    首先外层枚举i,再枚举j,如果j可选,就枚举26个字符k,f[i][j]就给j沿着k往下能走到的状态(包括走fail)v贡献

    能理解这道题怎么写,但是似乎不能往更广泛的地方延伸,想不动东西……感觉状态不是很好啊QAQ

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 const int dalao=10007;
     8 int rd(){int z=0,mk=1;  char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
    10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    11     return z*mk;
    12 }
    13 int n,m;
    14 char s[110];  int ls;
    15 int nxt[6100][26],fl[6100],tt=0;
    16 int q[6100],hd=0;
    17 bool mk[6100];
    18 int f[110][6100];
    19 void ist(){
    20     int tmp=0;
    21     for(int i=1;i<=ls;++i){
    22         if(!nxt[tmp][s[i]-'A'])  nxt[tmp][s[i]-'A']=++tt;
    23         tmp=nxt[tmp][s[i]-'A'];
    24     }
    25     mk[tmp]=true;
    26 }
    27 void gtac(){
    28     for(int i=0;i<26;++i)if(nxt[0][i])  q[++hd]=nxt[0][i];
    29     for(int k=1;k<=hd;++k)for(int i=0;i<26;++i){
    30         if(!nxt[q[k]][i])  nxt[q[k]][i]=nxt[fl[q[k]]][i];
    31         else{
    32             fl[nxt[q[k]][i]]=nxt[fl[q[k]]][i],q[++hd]=nxt[q[k]][i];
    33             mk[nxt[q[k]][i]]|=mk[nxt[fl[q[k]]][i]];
    34         }
    35     }
    36 }
    37 int main(){//freopen("ddd.in","r",stdin);
    38     cin>>n>>m;
    39     for(int i=1;i<=n;++i)  scanf("%s",s+1),ls=strlen(s+1),ist();
    40     gtac();
    41     f[0][0]=1;
    42     for(int i=1;i<=m;++i)for(int j=0;j<=tt;++j)if(!mk[j] && f[i-1][j])
    43         for(int k=0;k<26;++k)
    44             f[i][nxt[j][k]]=(f[i][nxt[j][k]]+f[i-1][j])%dalao;
    45     int bwl=0,ans=1;
    46     for(int i=1;i<=m;++i)  ans=(ans*26)%dalao;
    47     for(int i=0;i<=tt;++i)if(!mk[i])  bwl=(bwl+f[m][i])%dalao;
    48     cout<<(ans-bwl+dalao)%dalao<<endl;
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    log4j1修改DailyRollingFileAppender支持日志最大数量
    log4j1 修改FileAppender解决当天的文件没有日期后缀
    log4j生成有日期的日志文件名
    Java删除List和Set集合中元素
    Java并发编程:并发容器之ConcurrentHashMap
    Java并发编程:并发容器之CopyOnWriteArrayList
    java.util.ConcurrentModificationException解决详解
    Handshake failed due to invalid Upgrade header: null 解决方案
    web项目Log4j日志输出路径配置问题
    log4j.properties 的使用详解
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6538129.html
Copyright © 2011-2022 走看看