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 }
  • 相关阅读:
    HDU 5486 Difference of Clustering 图论
    HDU 5481 Desiderium 动态规划
    hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值
    HDU 5478 Can you find it 随机化 数学
    HDU 5477 A Sweet Journey 水题
    HDU 5476 Explore Track of Point 数学平几
    HDU 5475 An easy problem 线段树
    ZOJ 3829 Known Notation 贪心
    ZOJ 3827 Information Entropy 水题
    zoj 3823 Excavator Contest 构造
  • 原文地址:https://www.cnblogs.com/guapisolo/p/9697141.html
Copyright © 2011-2022 走看看