HDU 2296
很明显的DP状态了,设dp[i][j],设当前在状态点i,经过j步能得到的最大分值。也是从root直接扩展就可以了。
至于字符串,实在有点困难,开始想着记录路径,但后来发现路径从后往前回溯不一定是字典序最小,夭折。。。看别人的,发现直接就把字符串存下来,跪了,也对,毕竟才50个。
直接存字符串,比较,选最小,即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <string.h>
#include <queue>
#include <cmath>
#include <map>
#include <vector>
#define LL __int64
using namespace std;
const int Maxn=1110;
const int dictsize=26;
const int root=0;
const int inf=(1<<30);
int fail[Maxn],trie[Maxn][dictsize];
int hv[Maxn];
int tag[Maxn];
int head,tail,tot;
int que[Maxn];
char str[Maxn];
int n,m,anshv;
int dp[Maxn][55];
char dpc[Maxn][55][55];
char ans[55];
void Insert_trie(int s){
int p=0,i=0,index;
while(str[i]){
index=str[i]-'a';
if(trie[p][index]==-1) trie[p][index]=++tot;
p=trie[p][index];
i++;
}
tag[p]=s;
}
void build_ac(){
head=tail=0;
que[tail++]=root;
while(head!=tail){
int tmp=que[head++];
int p=-1;
for(int i=0;i<dictsize;i++){
if(trie[tmp][i]!=-1){
if(tmp==root) fail[trie[tmp][i]]=root;
else{
p=fail[tmp];
while(p!=-1){
if(trie[p][i]!=-1){
fail[trie[tmp][i]]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-1) fail[trie[tmp][i]]=root;
}
if(tag[fail[trie[tmp][i]]]>=0) tag[trie[tmp][i]]=tag[fail[trie[tmp][i]]];
que[tail++]=trie[tmp][i];
}
else{ //trie[tmp][i]==-1
if(tmp==root) trie[tmp][i]=root;
else{
p=fail[tmp];
while(p!=-1){
if(trie[p][i]!=-1){
trie[tmp][i]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-1) trie[tmp][i]=root;
}
}
}
}
}
bool cmp(char s1[],char s2[])
{
int len1=strlen(s1);
int len2=strlen(s2);
if(len1 != len2)return len1 < len2;
else return strcmp(s1,s2) < 0;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
head=tail=tot=0;
memset(fail,-1,sizeof(fail));
memset(trie,-1,sizeof(trie));
memset(tag,-1,sizeof(tag));
for(int i=0;i<m;i++){
scanf("%s",str);
Insert_trie(i);
}
for(int i=0;i<m;i++)
scanf("%d",&hv[i]);
build_ac();
// cout<<"YES"<<endl;
for(int i=0;i<=tot;i++){
for(int j=0;j<=n;j++){
strcpy(dpc[i][j],"");
dp[i][j]=-1;
}
}
dp[0][0]=0;
strcpy(ans,"");
anshv=0;
for(int j=0;j<n;j++){
for(int i=0;i<=tot;i++){
if(dp[i][j]>=0){
strcpy(str,dpc[i][j]);
int len=strlen(str);
for(int k=0;k<dictsize;k++){
int son=trie[i][k];
str[len]='a'+k;
str[len+1]='\0';
int tt=dp[i][j];
if(tag[son]>=0)
tt+=hv[tag[son]];
if(dp[son][j+1]<tt||(tt==dp[son][j+1]&&cmp(str,dpc[son][j+1]))){
dp[son][j+1]=tt;
strcpy(dpc[son][j+1],str);
}
if(dp[son][j+1]>anshv||dp[son][j+1]==anshv&&cmp(dpc[son][j+1],ans)){
anshv=dp[son][j+1];
strcpy(ans,dpc[son][j+1]);
}
}
}
}
}
puts(ans);
}
return 0;
}

浙公网安备 33010602011771号