zoukankan      html  css  js  c++  java
  • [Bzoj1030][JSOI2007]文本生成器(AC自动机&dp)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1030

    最最最常见的多串匹配问题!题目求至少包含一个子串的方案数,则可以转化成全部方案-不包含子串的方案数。

    求不包含任何字串的方案数即以所有子串建AC自动机,然后跑dp,dp[i][j]表示长度为i,在AC自动机上标号为j的点的子串方案数。

    $ans=sum_{i=0}^{len-1} dp[n][i]$,len为AC自动机节点编号。

    最后用总方案数-ans即为最后答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 2e5 + 10;
     4 typedef long long ll;
     5 const int mod = 10007;
     6 struct node {
     7     int AC[60010][26];
     8     int End[60010];
     9     int fail[60010];
    10     int dp[110][60010];
    11     int len, root;
    12     int newcode() {
    13         memset(AC[len], -1, sizeof(AC[len]));
    14         End[len] = 0;
    15         len++;
    16         return len - 1;
    17     }
    18     void init() {
    19         len = 0;
    20         root = newcode();
    21     }
    22     void build(string s) {
    23         int k = s.size();
    24         int now = root;
    25         for (int i = 0; i < k; i++) {
    26             if (AC[now][s[i] - 'A'] == -1)
    27                 AC[now][s[i] - 'A'] = newcode();
    28             now = AC[now][s[i] - 'A'];
    29         }
    30         End[now] = 1;
    31     }
    32     void getFail() {
    33         queue<int>q;
    34         fail[root] = root;
    35         for (int i = 0; i < 26; i++) {
    36             if (AC[root][i] != -1) {
    37                 fail[AC[root][i]] = root;
    38                 q.push(AC[root][i]);
    39             }
    40             else
    41                 AC[root][i] = root;
    42         }
    43         while (!q.empty()) {
    44             int now = q.front();
    45             q.pop();
    46             End[now] |= End[fail[now]];
    47             for (int i = 0; i < 26; i++) {
    48                 if (AC[now][i] != -1) {
    49                     fail[AC[now][i]] = AC[fail[now]][i];
    50                     q.push(AC[now][i]);
    51                 }
    52                 else
    53                     AC[now][i] = AC[fail[now]][i];
    54             }
    55         }
    56     }
    57     int solve(int n) {
    58         for (int i = 1; i <= n; i++)
    59             for (int j = 0; j <= len; j++)
    60                 dp[0][0] = 0;
    61         dp[0][0] = 1;
    62         for (int i = 1; i <= n; i++) {
    63             for (int j = 0; j < len; j++) {
    64                 for (int k = 0; k < 26; k++) {
    65                     if (End[AC[j][k]] == 1)
    66                         continue;
    67                     dp[i][AC[j][k]] += dp[i - 1][j];
    68                     dp[i][AC[j][k]] %= mod;
    69                 }
    70             }
    71         }
    72         int ans = 0;
    73         for (int i = 0; i < len; i++)
    74             ans = (ans + dp[n][i]) % mod;
    75         return ans;
    76     }
    77 }AC;
    78 int main() {
    79     string s;
    80     int n, m;
    81     scanf("%d%d", &n, &m);
    82     AC.init();
    83     for (int i = 1; i <= n; i++) {
    84         cin >> s;
    85         AC.build(s);
    86     }
    87     AC.getFail();
    88     int ans = AC.solve(m);
    89     int sum = 1;
    90     for (int i = 1; i <= m; i++)
    91         sum = sum * 26 % mod;
    92     printf("%d
    ", (sum - ans + mod) % mod);
    93 }
  • 相关阅读:
    root用户Linux 环境变量的配置解决(-bash: jps: command not found)有关问题
    Linux Crontab内环境变量与Shell环境变量的关系及解决问题的办法
    RocketMQ os.sh 系统优化(CentOS)
    Spring Boot修改内置Tomcat端口号
    SpringBoot多跨域请求的支持(JSONP)
    [译]Spring Boot 构建一个RESTful Web服务
    delphi怎样把子窗体显示在pagecontrol的tabsheet
    delphi从TRichEdit获得RTF格式文本(PC版本)
    数据类型表(DELPHI、C++)
    对程序进行注释
  • 原文地址:https://www.cnblogs.com/sainsist/p/11134605.html
Copyright © 2011-2022 走看看