很明显的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]=' '; 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; }