• BZOJ2580:[USACO]Video Game(AC自动机,DP)


    Description

    Bessie is playing a video game! In the game, the three letters 'A', 'B', and 'C' are the only valid buttons. Bessie may press the buttons in any order she likes; however, there are only N distinct combos possible (1 <= N <= 20). Combo i is represented as a string S_i which has a length between 1 and 15 and contains only the letters 'A', 'B', and 'C'. Whenever Bessie presses a combination of letters that matches with a combo, she gets one point for the combo. Combos may overlap with each other or even finish at the same time! For example if N = 3 and the three possible combos are "ABA", "CB", and "ABACB", and Bessie presses "ABACB", she will end with 3 points. Bessie may score points for a single combo more than once. Bessie of course wants to earn points as quickly as possible. If she presses exactly K buttons (1 <= K <= 1,000), what is the maximum number of points she can earn?
    给出n个ABC串combo[1..n]和k,现要求生成一个长k的字符串S,问S与word[1..n]的最大匹配数

    Input

    Line 1: Two space-separated integers: N and K. * Lines 2..N+1: Line i+1 contains only the string S_i, representing combo i.

    Output

    Line 1: A single integer, the maximum number of points Bessie can obtain.

    Sample Input

    3 7 ABA CB ABACB

    Sample Output

    4

    HINT

    The optimal sequence of buttons in this case is ABACBCB, which gives 4 points--1 from ABA, 1 from ABACB, and 2 from CB.

    Solution

    用$End[i]$表示$i$结点及其所有的后缀(也就是其$fail$树上所有祖先)的字符串个数。

    设$f[i][j]$表示匹配到$i$点,长度为$j$,转移比较显然。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 #define N (1009)
     6 using namespace std;
     7 
     8 int n,k,cnt,ans,f[N][N];
     9 int Son[N][3],End[N],Fail[N];
    10 char s[N];
    11 queue<int>q;
    12 
    13 void Insert(char s[])
    14 {
    15     int now=0,len=strlen(s);
    16     for (int i=0; i<len; ++i)
    17     {
    18         int x=s[i]-'A';
    19         if (!Son[now][x]) Son[now][x]=++cnt;
    20         now=Son[now][x];
    21     }
    22     ++End[now];
    23 }
    24 
    25 void Build_Fail()
    26 {
    27     for (int i=0; i<3; ++i)
    28         if (Son[0][i]) q.push(Son[0][i]);
    29     while (!q.empty())
    30     {
    31         int now=q.front(); q.pop();
    32         End[now]+=End[Fail[now]];
    33         for (int i=0; i<3; ++i)
    34         {
    35             if (!Son[now][i])
    36             {
    37                 Son[now][i]=Son[Fail[now]][i];
    38                 continue;
    39             }
    40             Fail[Son[now][i]]=Son[Fail[now]][i];
    41             q.push(Son[now][i]);
    42         }
    43     }
    44 }
    45 
    46 int main()
    47 {
    48     scanf("%d%d",&n,&k);
    49     for (int i=1; i<=n; ++i)
    50         scanf("%s",s), Insert(s);
    51     Build_Fail();
    52     memset(f,-0x7f,sizeof(f));
    53     f[0][0]=0;
    54     for (int i=0; i<=k; ++i)
    55         for (int j=0; j<=cnt; ++j)
    56             for (int k=0; k<3; ++k)
    57                 f[Son[j][k]][i+1]=max(f[Son[j][k]][i+1],f[j][i]+End[Son[j][k]]);
    58     for (int i=1; i<=cnt; ++i) ans=max(ans,f[i][k]);
    59     printf("%d
    ",ans);
    60 }
  • 相关阅读:
    三元操作符的类型务必一致
    a++ 和 ++a 的区别
    TCP/IP四层协议模型与ISO七层模型
    CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置
    修改gcc/g++默认include路径
    js中Math.random()生成指定范围数值的随机数
    在 QML 中创建 C++ 导入类型的实例
    QML从文件加载组件简单示例
    Android插件化开发---执行未安装apk中的Service
    游戏开发热门技术浅析
  • 原文地址:https://www.cnblogs.com/refun/p/10430723.html
Copyright © 2020-2023  润新知