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);
    }
    

      

  • 相关阅读:
    webpack入门
    vue 知识记录
    vue 服务端渲染案例
    nodemon的简单配置和使用
    vue 非父子组件通信-中转站
    position笔记
    koa 练习
    笔记
    git push代码时的'git did not exit cleanly (exit code 1)'问题解决
    块级元素的text-align对行内元素和果冻元素(inline-block)的作用
  • 原文地址:https://www.cnblogs.com/cutemush/p/12611320.html
Copyright © 2011-2022 走看看