• [JSOI2007]文本生成器


    题目大意:
      给定$n(nle60)$个字符串$s_i(|s_i|le100)$,问有多少个长度为$m(mle100)$的字符串$t$满足至少包含一个$s_i$?保证所有字符串均由大写英文字母构成。

    思路:
      建立AC自动机。用$f[i][j]$表示构造到$t$的第$i$位,对应自动机上编号为$j$的结点,不包含任何$s_i$的方案数。显然遇到危险结点需要跳过,否则直接转移即可。答案即为$26^m-sum f[m][i]$。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int N=60,L=101,S=26,mod=10007;
    12 char s[L];
    13 int f[L][N*L];
    14 class AhoCorasick {
    15     private:
    16         bool val[N*L];
    17         std::queue<int> q;
    18         int ch[N*L][S],fail[N*L];
    19         int sz,new_node() {
    20             return ++sz;
    21         }
    22         int idx(const int &c) const {
    23             return c-'A';
    24         }
    25     public:
    26         void insert(const char s[]) {
    27             int p=0;
    28             for(register int i=0;s[i];i++) {
    29                 const int c=idx(s[i]);
    30                 p=ch[p][c]?:ch[p][c]=new_node();
    31             }
    32             val[p]=true;
    33         }
    34         void get_fail() {
    35             for(register int c=0;c<S;c++) {
    36                 if(ch[0][c]) q.push(ch[0][c]);
    37             }
    38             while(!q.empty()) {
    39                 const int &x=q.front();
    40                 for(register int c=0;c<S;c++) {
    41                     int &y=ch[x][c];
    42                     if(!y) {
    43                         y=ch[fail[x]][c];
    44                         continue;
    45                     }
    46                     fail[y]=ch[fail[x]][c];
    47                     val[y]|=val[fail[y]];
    48                     q.push(y);
    49                 }
    50                 q.pop();
    51             }
    52         }
    53         int solve(const int &n,const int &m) const {
    54             int ret=f[0][0]=1;
    55             for(register int i=1;i<=m;i++) {
    56                 (ret*=S)%=mod;
    57                 for(register int j=0;j<=sz;j++) {
    58                     if(!f[i-1][j]) continue;
    59                     for(register int c=0;c<S;c++) {
    60                         if(!val[ch[j][c]]) (f[i][ch[j][c]]+=f[i-1][j])%=mod;
    61                     }
    62                 }
    63             }
    64             for(register int i=0;i<=sz;i++) {
    65                 ret=(ret-f[m][i]+mod)%mod;
    66             }
    67             return ret;
    68         }
    69 };
    70 AhoCorasick ac;
    71 int main() {
    72     const int n=getint(),m=getint();
    73     for(register int i=0;i<n;i++) {
    74         scanf("%s",s);
    75         ac.insert(s);
    76     }
    77     ac.get_fail();
    78     printf("%d
    ",ac.solve(n,m));
    79     return 0;
    80 }
  • 相关阅读:
    读取csv文件时编码错误
    ubuntu keras
    ubuntu19.1 tensorflow
    随机数random
    获取文件夹下所有文件名
    np.random.send()
    tensorflow---识别图像特征(吴恩达课程)
    Springboot项目热部署-Devtools
    Hadoop综合大作业
    分布式文件系统HDFS 练习
  • 原文地址:https://www.cnblogs.com/skylee03/p/8574182.html
Copyright © 2020-2023  润新知