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

  

posted @ 2015-03-03 22:07  chenjunjie1994  阅读(146)  评论(0编辑  收藏  举报