您的位置:首页 > 其它

hdu 2296(AC自动机+dp)

2013-05-16 23:51 465 查看
题意:容易理解...

分析:这个题我做了几天,不是说这个题有多难,而是因为我太水了(比较两个字符串的大小都弄错了)。首先是状态转移方程,这个还是比较容易的: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: