zoukankan      html  css  js  c++  java
  • 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;
    }
    

      

  • 相关阅读:
    suse12安装详解
    Centos7上部署openstack mitaka配置详解(将疑难点都进行划分)
    菜鸟帮你跳过openstack配置过程中的坑[文末新添加福利]
    openstack中dashboard页面RuntimeError: Unable to create a new session key. It is likely that the cache is unavailable.
    Multiple network matches found for name 'selfservice', use an ID to be more specific.报错
    查看 SELinux状态及关闭SELinux
    SELinux深入理解
    IP地址、子网掩码、网络号、主机号、网络地址、主机地址
    Oracle job procedure 存储过程定时任务
    POI文件导出至EXCEL,并弹出下载框
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4312022.html
Copyright © 2011-2022 走看看