• 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]='';
    						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;
    }
    

      

  • 相关阅读:
    MySQL-EXPLAIN执行计划字段解释
    MySQL-EXPLAIN执行计划Extra解释
    HTTP与HTTPS的区别
    【面试】Java中sleep和wait的区别
    Nginx之前后端分离(入门)
    玩程序 之 一 . 字符串处理工具(可通过C#脚本扩展)
    C#实现下载功能,可用于软件自动更新
    对c#剪切板Clipboard占用的问题一点解决方法
    C# 制作 仪表
    C#使用自定义字体(从文件获取)
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4312022.html
Copyright © 2020-2023  润新知