HDU 2296

来源:互联网 发布:linux下重启的命令 编辑:程序博客网 时间:2024/06/04 00:35

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