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

原文地址:https://www.cnblogs.com/jiangjing/p/3082930.html