zoukankan      html  css  js  c++  java
  • hdu 2296(AC自动机+dp)

    题意:容易理解...

    分析:这个题我做了几天,不是说这个题有多难,而是因为我太水了(比较两个字符串的大小都弄错了)。首先是状态转移方程,这个还是比较容易的:dp[i][j]=dp[i-1][k]+(这个点的权值);如果是单纯的让你求出最大的权值,那就比较简单了,但是题意让你输出的事权值最大的字符串,如果两个字符串的权值是相等的话:先比较字符串的长度,取短者,如果长度也相等的话,就取字典序小的。我用str[i][j][k]数组记录长度为i,然后以j节点结尾的权值最大的字符串,用dp[i][j]表示长度为i以j节点结尾的权值最大的。

    代码实现:

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<iostream>
    #include<queue>
    using namespace std;
    struct node{
        int next[26];
        int fail;
        int val;
        void init()
        {
            memset(next,0,sizeof(next));
            fail=0;
            val=0;
        }
    }a[1200];
    int tot,len;
    int dp[55][1200];
    char str[55][1200][55];

    void chushihua()
    {
        memset(dp,-1,sizeof(dp));
        tot=0;
        a[0].init();
    }

    void insert(char *str,int v)
    {
        int index,p=0;
        for(;*str!='\0';str++)
        {
            index=*str-'a';
            if(a[p].next[index]==0)
            {
                a[++tot].init();
                a[p].next[index]=tot;
            }
            p=a[p].next[index];
        }
        a[p].val=v;
    }

    void build_ac()
    {
        queue<int>Q;
        int p,cur,son,i;
        Q.push(0);
        while(!Q.empty())
        {
            p=Q.front();
            Q.pop();
            for(i=0;i<26;i++)
            {
                if(a[p].next[i]!=0)
                {
                    son=a[p].next[i];
                    cur=a[p].fail;
                    if(p==0)
                        a[son].fail=0;
                    else
                    {
                        while(cur&&a[cur].next[i]==0)
                            cur=a[cur].fail;
                        a[son].fail=a[cur].next[i];
                    }
                    if(a[a[son].fail].val)
                        a[son].val+=a[a[son].fail].val;
                    Q.push(son);
                }
                else
                    a[p].next[i]=a[a[p].fail].next[i];
            }
        }
    }

    void solve()
    {
        int i,j,k,son,max=0;
        char shang[55],temp,res[55];
        dp[0][0]=0;
        strcpy(str[0][0],"\0");
        strcpy(res,"\0");
        for(i=1;i<=len;i++)
            for(j=0;j<=tot;j++)
            {
                if(dp[i-1][j]==-1)
                    continue;
                strcpy(shang,str[i-1][j]);
                for(k=0;k<26;k++)
                {
                    son=a[j].next[k];
                    temp=k+'a';
                    shang[i-1]=temp;
                    shang[i]='\0';
                    if(dp[i][son]==-1)
                    {
                        dp[i][son]=dp[i-1][j]+a[son].val;
                        strcpy(str[i][son],shang);
                    }
                    else
                    {
                        if(dp[i][son]<dp[i-1][j]+a[son].val)
                        {
                            dp[i][son]=dp[i-1][j]+a[son].val;
                            strcpy(str[i][son],shang);
                        }
                        else if(dp[i][son]==dp[i-1][j]+a[son].val)
                        {
                            if(strcmp(str[i][son],shang)>0)
                                 strcpy(str[i][son],shang);
                        }
                    }
                }
            }

            for(i=1;i<=len;i++)
                for(j=0;j<=tot;j++)
                {
                    if(dp[i][j]>max)
                    {
                        max=dp[i][j];
                        strcpy(res,str[i][j]);
                    }
                    else if(dp[i][j]==max&&strcmp(res,str[i][j])>0&&strlen(res)>=strlen(str[i][j]))
                        strcpy(res,str[i][j]);                
                }
            printf("%s\n",res);
    }

    int main()
    {
        char keyword[105][15];
        int n,T,val[105],i;
        while(scanf("%d",&T)!=EOF)
        {
            while(T--)
            {
                chushihua();
                scanf("%d%d",&len,&n);
                getchar();
                for(i=0;i<n;i++)
                     scanf("%s",keyword[i]);
                for(i=0;i<n;i++)
                     scanf("%d",&val[i]);
                for(i=0;i<n;i++)
                     insert(keyword[i],val[i]);
                build_ac();
                solve();
            }
        }
        return 0;
    }

  • 相关阅读:
    页面转表格并且下载
    关于表格导入
    C/C++作用域运算符::
    设计模式之观察者模式_C++
    C# 传不定参数
    C语言中的位域的使用
    C++/python求哈希值(SHA256)
    C++中纯虚函数
    类模板/函数模板实现父类指针指向子类对象(虚函数实现多态)
    Windows Socket 接口简介
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3082930.html
Copyright © 2011-2022 走看看