AC自动机水题,随便写写就过了,注意记录最优的字符串,保证同等分值情况下最短,长度相同的时候字典序最小就行了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define N 1100
#define Max 26
typedef long long LL;
using namespace std;
struct node
{
int id,num;
node *next[Max],*fail;
} tree[N],*root;
int cnt;
int val[105];
node* newnode()
{
for(int i = 0; i<Max; i++) tree[cnt].next[i] = NULL;
tree[cnt].fail = NULL;
tree[cnt].num = 0;
tree[cnt].id = cnt;
return &tree[cnt++];
}
void insert(char *str,int x)
{
int i=0,s;
node *t=root;
while(str[i])
{
s=str[i]-'a';
if(t->next[s]==NULL)
t->next[s]=newnode();
t=t->next[s];
i++;
}
t->num = val[x];
}
void build_ac_automation()
{
queue<node *>q;
node *tmp=root;
q.push(tmp);
while(!q.empty())
{
tmp=q.front();
q.pop();
for(int i=0; i<Max; i++)
if(tmp->next[i]==NULL)
{
if(tmp==root)tmp->next[i]=root;
else tmp->next[i]=tmp->fail->next[i];
}
else
{
if(tmp==root)tmp->next[i]->fail=root;
else
{
tmp->next[i]->fail=tmp->fail->next[i];
tmp->next[i]->num+=tmp->fail->next[i]->num;
}
q.push(tmp->next[i]);
}
}
}
char s[105][20];
int dp[55][N];
string str[55][N];
int main()
{
int t,n,m,i,j,k;
scanf("%d",&t);
while(t--)
{
cnt = 0;
root = newnode();
scanf("%d%d",&n,&m);
for(i = 1; i<=m; i++)scanf("%s",s[i]);
for(i = 1; i<=m; i++)
{
scanf("%d",&val[i]);
insert(s[i],i);
}
build_ac_automation();
memset(dp,-1,sizeof(dp));
dp[0][0] = 0;
str[0][0] = "";
for(i = 0; i<n; i++)
{
for(j = 0;j<cnt;j++)
{
if(dp[i][j] == -1)continue;
dp[i+1][j] = dp[i][j];
str[i+1][j] = str[i][j];
}
for(j = 0; j<cnt; j++)
{
if(dp[i][j] == -1)continue;
for(k = 0; k<26; k++)
{
int v = tree[j].next[k]->id;
int tmp = tree[j].next[k]->num;
if(dp[i][j]+tmp>dp[i+1][v])
{
dp[i+1][v] = dp[i][j]+tmp;
str[i+1][v] = str[i][j]+(char)('a'+k);
}
else if(dp[i][j]+tmp == dp[i+1][v])
{
string nstr = str[i][j]+(char)('a'+k);
if(nstr.length()<str[i+1][v].length())
str[i+1][v] = nstr;
else if(nstr.length() == str[i+1][v].length())
if(nstr<str[i+1][v])
str[i+1][v] = nstr;
}
}
}
}
int ans = 0;
string astr;
for(i = 0; i<cnt; i++)
{
if(dp[n][i]>ans)
{
ans = dp[n][i];
astr = str[n][i];
}
else if(dp[n][i] == ans)
{
if(str[n][i].length()<astr.length())
astr = str[n][i];
else if(astr.length() == str[n][i].length())
if(astr>str[n][i])
astr = str[n][i];
}
}
cout<<astr<<endl;
}
return 0;
}