http://acm.hdu.edu.cn/showproblem.php?pid=2296
题意: 给你若干个字符串每个字符串有自己的价值,之后要求构建出长度为n的字符串 所能形成的串的价值最大,并且保持字典序最小并把那个串输出。
注:
2
7 2
love
ever
5 5
对于样例,我们要构建长度为7的串,并且只有love ever有价值并且价值都为5。所以我们可以想象,我们要保持价值最大,那么我们只要构建出 lovever即可。 价值为10;所以输出lovever
#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <algorithm>
#include <string.h>
#define maxs 1022
#define BUG puts("BUG2")
#define MME(i,j) memset(i,j,sizeof(i))
using namespace std;
int nexts[1010][27],endval[maxs],fail[maxs];
int root,L;
int newnode()
{
MME(nexts[L],-1);
endval[L]=0;
L++;
return L-1;
}
void init()
{
L=0;
MME(fail,0);
MME(endval,0);
root =newnode();
}
string s[maxs],path[maxs][115],str;
int dp[maxs][115],ans;
void Insert(string ss,int val)
{
int now=root,id,i=0;
while(ss[i])
{
id = ss[i]-'a';
if(nexts[now][id]==-1)
nexts[now][id]=newnode();
now = nexts[now][id];
i++;
}
endval[now]=val;
}
void build()
{
queue<int>Q;
for(int i=0; i<26; i++)
if(nexts[root][i]==-1)
nexts[root][i]=root;
else
{
fail[nexts[root][i]]=root;
Q.push(nexts[root][i]);
}
int now;
while(!Q.empty())
{
now =Q.front();
Q.pop();
for(int i=0; i<26; i++)
{
if(nexts[now][i]==-1)
nexts[now][i]=nexts[fail[now]][i];
else
{
fail[ nexts[now][i] ]=nexts[fail[now]][i];
endval[ nexts[now][i] ] +=endval[ fail[ nexts[now][i] ] ] ; //这里 当前节点的价值要加上失败指针所指向的结点的价值,因为你当前节点失败匹配后,会转向失败指针。所以说当前节点的价值为他俩之和。
Q.push( nexts[now][i] );
}
}
}
}
string cmp(string a,string b)
{
if(a=="")
return a;
if(a.size()==b.size())
return a<b?a:b;
else
return a.size() < b.size()? a:b;
}
void solve(int n) /// n 为选择字符串长度
{
ans = 0;
str="";
for(int i=0; i<L; i++)
for(int j=0; j<=n; j++) // Update,更新所以长度以及所以状态。
{
dp[i][j]=-1;
path[i][j]="";
}
dp[0][0]=0;
char tmp;
int i,son;
for(int len=0; len<n; len++) //枚举所有长度
{
for(i=0; i<L; i++)// 枚举所有状态
{
if(dp[i][len]==-1)
continue;
for(son=0; son<26; son++)//这里是当前状态下的儿子
{
if(dp[ nexts[i][son] ][ len+1 ] <= dp[ i ][ len ] + endval[ nexts[i][son] ])
{
tmp = 'a'+son;
if( dp[nexts[i][son]][len+1] < dp[i][len] + endval[ nexts[i][son] ] )
{
dp[ nexts[i][son] ][ len+1 ] = dp[ i ][ len ] + endval[ nexts[i][son] ] ;
path[ nexts[i][son] ][ len+1 ] = path[ i ][ len ] + tmp;
}
else
{
path[ nexts[i][son] ][ len+1 ] = cmp( path[ nexts[i][son] ][ len+1 ],path[ i ][ len ] + tmp );
}
if( ans < dp[ nexts[i][son] ][ len+1 ] )
{
ans = dp[ nexts[i][son] ][ len+1 ];
str = path[ nexts[i][son] ][ len+1 ];
}
else if(ans == dp[ nexts[i][son] ][ len+1 ] )
{
str = cmp(str,path[ nexts[i][son] ][ len+1 ] );
}
}
}
}
}
if(ans == 0 )
cout<<endl;
else
cout<<str<<endl;
}
int main()
{
int t,n,m;
cin>>t;
while(t--)
{
cin>>n>>m;
init();
for(int i=0; i<m; i++)
{
cin>>s[i];
}
int v;
for(int i=0; i<m; i++)
{
cin>>v;
Insert(s[i],v);
}
build();
solve(n);
}
return 0;
}