zoukankan      html  css  js  c++  java
  • [USACO12JAN]Video Game Combos


    贝西在玩一款游戏,该游戏只有三个技能键 “A”“B”“C”可用,但这些键可用形成N种(1 <= N<= 20)特定的组合技。第i个组合技用一个长度为1到15的字符串S_i表示。

    当贝西输入的一个字符序列和一个组合技匹配的时候,他将获得1分。特殊的,他输入的一个字符序列有可能同时和若干个组合技匹配,比如N=3时,3种组合技分别为"ABA", “CB”, 和"ABACB",若贝西输入"ABACB",他将获得3分。

    若贝西输入恰好K (1 <= K <= 1,000)个字符,他最多能获得多少分?

    输入
    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.

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

    样例输入
    3 7
    ABA
    CB
    ABACB

    样例输出
    4

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


    多字符串匹配,先搞出ac自动机,然后我们设dp[i][j],为当前匹配到第i个数,
    上一次在ac自动机的第j位,很显然得出方程f[i+1][j”]=max(f[i+1][j”],f[i][j]+当前这一位取某个ABC的贡献);

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cstring>
    using namespace std;
      
    int n,k,cnt,m;
    int son[400][3],fail[400],sum[400],dp[1010][400],q[2000];
    char s[30];
      
    void insert()
    {
        int p=0;
        for (int i=0;s[i];i++)
        {
            if (!son[p][s[i]-'A']) 
                son[p][s[i]-'A']=++cnt;
            p=son[p][s[i]-'A'];
        }
        sum[p]++;
    }
      
    void getfail()
    {
        int head=1,tail=0;
        for (int i=0;i<3;i++)
        { 
            if (!son[0][i]) 
                 son[0][i]=++cnt;
            q[++tail]=son[0][i];
        }
        while (head<=tail)
        {
            int now=q[head++];
            for (int i=0;i<3;i++)
                if (son[now][i])
                {
                    q[++tail]=son[now][i];
                    fail[son[now][i]]=son[fail[now]][i];
                    sum[son[now][i]]+=sum[son[fail[now]][i]];
                }
                else son[now][i]=son[fail[now]][i];
        }
    }
      
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            insert();
        }
        getfail();
        memset(dp,-2,sizeof dp);
        dp[0][0]=0;
        for (int i=1;i<=m;i++)
            for (int j=0;j<=cnt;j++)
                for (int k=0;k<3;k++)
                    dp[i][son[j][k]]=max(dp[i][son[j][k]],dp[i-1][j]+sum[son[j][k]]);
        int ans=0;
        for (int i=0;i<=cnt;i++) 
              ans=max(ans,dp[m][i]);
        printf("%d",ans);
        return 0;
    }
    

      

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define N 1005
    std::queue<int>q;
    int t[N][3],fail[N],val[N],vis[N][N],dp[N][N];
    char c[N];
    int n,m,cnt,ans;
    void ins(){
        int len=strlen(c),now=0;
        for (int i=0;i<len;i++)
    	{
            int u=c[i]-'A';
            if (t[now][u]) 
    		     now=t[now][u];
            else 
    		     now=t[now][u]=++cnt;
        }
        val[now]++;
    }
    
    void getfail()
    {
        for (int i=0;i<3;i++)
         if (t[0][i]) q.push(t[0][i]);
        fail[0]=0;
        while (!q.empty())
    	{
            int u=q.front();
            q.pop();
            for (int i=0;i<3;i++)
    		{
                int v=t[u][i];
                if (v) 
    			    fail[v]=t[fail[u]][i],q.push(v);
                else 
    			    t[u][i]=t[fail[u]][i];
            }
        }
    }
    
    int solve(int x,int y)
    {
        while (x) 
    	   y+=val[x],x=fail[x];
        return y;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
    	{
            scanf("%s",c);
            ins();
        }
        getfail(); 
    	vis[0][0]=1;
        for (int i=0;i<m;i++)
    	{
            for (int j=0;j<=cnt;j++)
    		{
                if (vis[i][j]==0) 
    			     continue;
                for (int k=0;k<3;k++)
    			{
                    int tmp=t[j][k];
                    //上一次走到了[i,j],现在从j这个点走到其子结点k 
                    dp[i+1][tmp]=std::max(dp[i+1][tmp],solve(tmp,dp[i][j]));
                    vis[i+1][tmp]=1;
                }
            }
        }
        for (int i=0;i<=cnt;i++) ans=std::max(ans,dp[m][i]);
        printf("%d",ans);
    }
    

      

  • 相关阅读:
    html 上传图片前预览
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    php 计算 pdf文件页数
    php 获取半年内每个月的订单数量, 总价, 月份
    php 获取两个数组之间不同的值
    小程序支付功能
    关于nginx的Job for nginx.service failed because the control process exited with error code.错误
    linux 安装 Apollo
    MongoDB待续。。。
    ABP vNext...待续
  • 原文地址:https://www.cnblogs.com/cutemush/p/12611320.html
Copyright © 2011-2022 走看看