zoukankan      html  css  js  c++  java
  • BZOJ 1030 [JSOI2007]文本生成器 (Trie图+DP)

    题目大意:给你一堆字符串,一个串不合法的条件是这些字符串中任意一个是这个串的子串,求合法的串的数量

    其实这道题比 [HNOI2008]GT考试 那道题好写一些,但道理是一样的

    只不过这道题的答案可以转化为 所有可能的字符串(26^m)数量 - 不合法的字符串数量

    定义f[i][j]表示匹配到了第i个字符,现在在Trie树上匹配到了第j个节点的方案数

    GT考试是跳Next,每次找出 和 插入这个字符后形成的字符串 具有相同最长后缀的位置

    那么对于Trie图来说,这不就是fail指针么

    Trie树被补全成Trie树后

    如果在原来的Trie树中某个节点x,它并没有儿子ch[x][c],那么在补全后,ch[x][c]自动指向的是x的fail指针指向的c儿子,即ch[fail[x]][c]

    这不正是我们想要转移的位置么,非常智能

    总结:字符串套KMP/AC自动机/Trie图的题,通常都有f[i][j]表示文本串匹配到了第i位,模式串匹配到了第j位这类状态,且有一些题可以用矩阵乘法优化。 

     1 #include <queue>
     2 #include <cmath>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 #define ll long long 
     7 #define N 6010
     8 #define M 28
     9 #define mod 10007
    10 #define ui unsigned int
    11 #define idx(x) (x-'A'+1)
    12 #define inf 0x3f3f3f3f
    13 using namespace std;
    14 //re
    15 int n,m;
    16 char str[65][110];
    17 int f[120][N];
    18 int qpow(int x,int y){
    19     int ans=1;
    20     while(y){
    21         if(y&1) ans=(ans*x)%mod;
    22         x=(x*x)%mod,y>>=1;
    23     }return ans;
    24 }
    25 struct Trie{
    26     int ch[N][M],fa[N],fail[N],ed[N],tot;
    27     void Build()
    28     {
    29         for(int i=1;i<=n;i++)
    30         {
    31             int len=strlen(str[i]+1),x=0;
    32             for(int j=1;j<=len;j++)
    33             {
    34                 int c=idx(str[i][j]);
    35                 if(!ch[x][c])
    36                     tot++,ch[x][c]=tot,fa[tot]=x;
    37                 x=ch[x][c];
    38                 if(j==len) ed[x]=1;
    39             }
    40         }
    41     }
    42     void Fail()
    43     {
    44         queue<int>q;
    45         for(int i=1;i<=26;i++)
    46             if(ch[0][i]) q.push(ch[0][i]);
    47         while(!q.empty())
    48         {
    49             int x=q.front();q.pop();
    50             for(int i=1;i<=26;i++)
    51                 if(ch[x][i])
    52                     fail[ch[x][i]]=ch[fail[x]][i],
    53                     q.push(ch[x][i]);
    54                 else 
    55                     ch[x][i]=ch[fail[x]][i];
    56         } 
    57     }
    58     int solve()
    59     {
    60         f[0][0]=1;
    61         queue<int>q;
    62         for(int i=0;i<=m;i++)
    63             for(int x=0;x<=tot;x++)
    64                 for(int c=1;c<=26;c++)
    65                 {
    66                     int flag=1;
    67                     for(int k=ch[x][c];k;k=fail[k])
    68                         if(ed[k]){flag=0;break;}
    69                     if(!flag) continue;
    70                     (f[i+1][ch[x][c]]+=f[i][x])%=mod;
    71                 }
    72         int ans=0;     
    73         for(int x=0;x<=tot;x++)
    74             if(!ed[x]) (ans+=f[m][x])%=mod;
    75         return ans;
    76     }
    77 }t;
    78 int main()
    79 {
    80     scanf("%d%d",&n,&m);
    81     for(int i=1;i<=n;i++) scanf("%s",str[i]+1);
    82     t.Build();
    83     t.Fail();
    84     printf("%u
    ",(qpow(26,m)-t.solve()+mod)%mod);
    85     return 0;
    86 }
  • 相关阅读:
    使用 C# 2008 Express Edition 编写的猜数字游戏
    话说三层
    在asp.net 1.1 中使用Ajax
    vs2005 调试时出现“无法附加。绑定句柄无效”的解决办法
    解决“你可能没有权限使用网络资源”的问题
    html&js 在firefox与IE中呈现存在差异的解决方法总结
    sql 事务 全攻略
    mssql的TSQL教程(从建登陆到建库、表和约束)(1)
    数据库练习题
    用批处理附加数据库
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9697141.html
Copyright © 2011-2022 走看看