• 【AC自动机】文本生成器


    【题目链接】

    https://loj.ac/problem/10063

    【题意】

    给出长度为m,n个模式串,请问只要长度为m的串中有一个模式串就算是可读。

    【分析】

    其实如果直接分析全部可读的情况,一个串,两个串,……n个串可读。

    明显是很复杂而且是做不出来的。

    正难则反,其实我们可以需要通过一个(所有可能-全部不可读的情况)不就是答案的方案吗?

    记录不合法的方案,考虑dp[i][j] ,下标为j,长度为i 的不可读的情况。

    其实不可读的情况就是不经过结尾的结点即可。

    最后答案就是利用26个字母,然后子节点通过父节点来累加答案。

    最后把对立事件算出来即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 const int N = 10005;
     8 const int M = 2e6+10;
     9 const int mod = 10007;
    10 int Trie[M][26] , fail[M] , End[M], idx ;
    11 int Q[M] , Head , Tail ;
    12 int f[N][N];
    13 int n ,m ;
    14 
    15 char str[N];
    16 
    17 void Insert( char s[] ){
    18     int p = 0;
    19     for(int i=0 ; s[i] ; i++ ){
    20         int t = s[i] - 'A' ;
    21         if( !Trie[p][t] )
    22             Trie[p][t] = ++idx ;
    23         p = Trie[p][t];
    24     }
    25     End[p] |= 1  ;
    26 }
    27 
    28 void Build(){
    29     Head = 1 , Tail = 0 ;
    30     for(int i=0;i<26;i++)
    31         if(Trie[0][i])
    32             Q[++Tail] = Trie[0][i] ;
    33 
    34     while( Head <= Tail ){
    35         int u = Q[Head++] ;
    36         for(int i=0;i<26;i++){
    37             int To = Trie[u][i];
    38             if( To ){
    39                 fail[To] = Trie[fail[u]][i];
    40                 Q[++Tail] = To;
    41 
    42                 End[To] |= End[fail[To]] ;
    43             }else{
    44                 Trie[u][i] = Trie[fail[u]][i];
    45             }
    46         }
    47     }
    48 
    49 }
    50 
    51 void Solve(){
    52     f[0][0] = 1 ;
    53     for(int i=1;i<=m;i++){
    54         for(int j=0;j<=idx;j++){
    55             for(int k=0;k<26;k++){
    56                 int To = Trie[j][k];
    57                 if( !End[To] ){
    58                     (f[i][To] += f[i-1][j]) %= mod ;
    59                 }
    60             }
    61         }
    62     }
    63     int tot = 0 ;
    64     for(int i=0;i<=idx;i++){
    65         tot = (tot+f[m][i]) % mod ;
    66     }
    67     int sum = 1 ;
    68     for(int i=1;i<=m;i++){
    69         sum = sum * 26 % mod ;
    70     }
    71     printf("%d
    ",(sum-tot+mod)%mod );
    72 }
    73 int main()
    74 {
    75     ios_base :: sync_with_stdio(false);
    76     cin.tie(0) , cout.tie(0);
    77     cin >> n >> m ;
    78     for(int i=0;i<n;i++){
    79         cin >> str ;
    80         Insert(str);
    81     }
    82     Build();
    83     Solve();
    84     return 0 ;
    85 }
    View Code
  • 相关阅读:
    搭建一个redis高可用系统
    从“如何设计用户超过1亿的应用”说起----数据库调优实战
    单表60亿记录等大数据场景的MySQL优化和运维之道 | 高可用架构
    信息安全系统和安全体系
    敏捷开发系列之旅 第五站(不一样的RUP统一软件开发过程)
    微服务理论与实践(三)-微服务架构的基本能力和优缺点
    学习“CC攻击”
    查看IIS错误日志
    ISNULL函数
    IE6/7下Select控件Display属性无效解决办法
  • 原文地址:https://www.cnblogs.com/Osea/p/11367081.html
Copyright © 2020-2023  润新知