zoukankan      html  css  js  c++  java
  • JSOI 2007 文本生成器 【AC自动机,树形DP】

    JSOI 2007 文本生成器

    题目见链接。

    题解:

    建立在 AC自动机 上的 树形DP。

    先把单词建立 trie 树,并标记是否为一个单词的结尾(bool : ed), 预处理 fail 指针, ed |= fail.ed

    然后求 可读,可以用 总的 减去 不可读的

    设 f[i][j] 表示 到了第 i 位,第 i 位上的节点编号为 j 的方案数,则

    f[i][son[j]] = (f[i-1][j] + f[i][son[j]] ) % mo 。

    最后用 ans - f[m][i] ( i 节点不为单词末尾)

     

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=6005,M=105,mo=10007;
     4 char s[N];
     5 int rt,tot,q[N],head,tail,ans1=1,ans2,f[M][N],n,m;
     6 struct node{
     7     int fail,nxt[26];
     8     bool ed;
     9 }e[N];
    10 inline void insert(char *s)
    11 {
    12     rt=0;
    13     for (int i=0; s[i]; ++i)
    14     {
    15         if (!e[rt].nxt[s[i]-'A'])
    16           e[rt].nxt[s[i]-'A']=++tot;
    17         rt=e[rt].nxt[s[i]-'A'];
    18     }
    19     e[rt].ed=1;
    20 }
    21 inline void getfail()
    22 {
    23     rt=0; head=tail=0;
    24     for (int i=0; i<26; ++i)
    25       if (e[rt].nxt[i]) q[++tail]=e[rt].nxt[i];
    26     while (head<tail)
    27     {
    28         int x=q[++head];
    29         for (int i=0; i<26; ++i)
    30           if (e[x].nxt[i])
    31           {
    32                 e[e[x].nxt[i]].fail=e[e[x].fail].nxt[i];
    33                 q[++tail]=e[x].nxt[i];
    34           }
    35           else e[x].nxt[i]=e[e[x].fail].nxt[i];
    36         e[x].ed|=e[e[x].fail].ed;
    37     }
    38 }
    39 inline void doing()
    40 {
    41     f[0][0]=1;
    42     for (int i=1; i<=m; ++i)
    43       for (int j=0; j<=tot; ++j)
    44       {
    45           if (e[j].ed) continue;
    46           for (int k=0; k<26; ++k)
    47             f[i][e[j].nxt[k]]=(f[i][e[j].nxt[k]]+f[i-1][j])%mo;
    48       }
    49     for (int i=0; i<=tot; ++i)
    50       if (!e[i].ed) ans2+=f[m][i];
    51     for (int i=1; i<=m; ++i)
    52       ans1=(ans1*26)%mo;
    53     printf("%d
    ",((ans1-ans2)%mo+mo)%mo);
    54 }
    55 int main()
    56 {
    57     scanf("%d%d",&n,&m);
    58     for (int i=1; i<=n; ++i)
    59       scanf("%s",s),insert(s);
    60     getfail();
    61     doing();
    62     return 0;
    63 }
    View Code

    fighting fighting fighting!!!

  • 相关阅读:
    麦卡姆轮运动原理
    ESP32开发(2)esp32-cam采集图像
    ESP32开发(1)环境配置
    Cesium学习笔记2-3:视频投影
    Cesium中实时显示经纬度及视角高
    Cesium学习笔记2-5:内部使用阳历扩展
    Cesium学习笔记2-4:外部扩展
    Cesium学习笔记2-4:更多官方示例
    win10通过wifi分享上网
    更换源地址
  • 原文地址:https://www.cnblogs.com/Frank-King/p/9683340.html
Copyright © 2011-2022 走看看