zoukankan      html  css  js  c++  java
  • HDU-2296 Ring(AC自动机+DP)

    题目大意:给出的m个字符串都有一个权值。用小写字母构造一个长度不超过n的字符串S,如果S包含子串s,则S获取s的权值。输出具有最大权值的最小字符串S。

    题目分析:先建立AC自动机。定义状态dp(step,u)表示长度为step、在u节点上的最大权值。状态转移方程为:dp(step,u)=max(dp(step-1,v)+w(u))。其中,v为能到达u的前一个节点。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<queue>
    # include<string>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    
    int cnt;
    int ch[1200][26];
    int fail[1200];
    int val[1200];
    int w[105];
    
    void init()
    {
    	cnt=0;
    	memset(ch,-1,sizeof(ch));
    	memset(val,0,sizeof(val));
    }
    
    int idx(char c)
    {
    	return c-'a';
    }
    
    void insert(char *s,int key)
    {
    	int len=strlen(s);
    	int r=0;
    	for(int i=0;i<len;++i){
    		int c=idx(s[i]);
    		if(ch[r][c]==-1) ch[r][c]=++cnt;
    		r=ch[r][c];
    	}
    	val[r]=w[key];
    }
    
    void getFail()
    {
    	queue<int>q;
    	fail[0]=0;
    	for(int i=0;i<26;++i){
    		if(ch[0][i]==-1)
    			ch[0][i]=0;
    		else{
    			fail[ch[0][i]]=0;
    			q.push(ch[0][i]);
    		}
    	}
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=0;i<26;++i){
    			if(ch[u][i]==-1)
    				ch[u][i]=ch[fail[u]][i];
    			else{
    				fail[ch[u][i]]=ch[fail[u]][i];
    				q.push(ch[u][i]);
    			}
    		}
    	}
    }
    
    char h[105][15];
    int dp[55][1200];
    string path[55][1200];
    
    bool isSmall(string s,string t)
    {
    	if(t=="") return true;
    	if(s.size()<t.size()) return true;
    	if(s.size()>t.size()) return false;
    	return s<t;
    }
    
    string DP(int n)
    {
    	memset(dp,-1,sizeof(dp));
    	dp[0][0]=0;
    	for(int i=0;i<=n;++i) for(int j=0;j<=cnt;++j)
    		path[i][j]="";
    	int fen=0;
    	for(int i=0;i<=n;++i){
    		for(int j=0;j<=cnt;++j){
    			if(dp[i][j]==-1) continue;
    			for(int c=0;c<26;++c){
    				if(dp[i+1][ch[j][c]]<dp[i][j]+val[ch[j][c]]){
    					dp[i+1][ch[j][c]]=dp[i][j]+val[ch[j][c]];
    					path[i+1][ch[j][c]]=path[i][j]+(char)('a'+c);
    				}else if(dp[i+1][ch[j][c]]==dp[i][j]+val[ch[j][c]]){
    					if(isSmall(path[i][j]+(char)('a'+c),path[i+1][ch[j][c]]))
    						path[i+1][ch[j][c]]=path[i][j]+(char)('a'+c);
    				}
    			}
    			if(i>0) fen=max(fen,dp[i][j]);
    		}
    	}
    	if(fen==0) return "";
    	string res="";
    	for(int i=1;i<=n;++i) for(int j=0;j<=cnt;++j){
    		if(dp[i][j]==fen&&isSmall(path[i][j],res)){
    			res=path[i][j];
    		}
    	}
    	return res;
    }
    
    int main()
    {
    	int T,n,m;
    	scanf("%d",&T);
    	while(T--)
    	{
    		init();
    		scanf("%d%d",&n,&m);
    		for(int i=0;i<m;++i)
    			scanf("%s",h[i]);
    		w[0]=0;
    		for(int i=1;i<=m;++i)
    			scanf("%d",w+i);
    		for(int i=0;i<m;++i)
    			insert(h[i],i+1);
    		getFail();
    		cout<<DP(n)<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    搜索回车跳转页面
    登录验证码
    【排序算法】排序算法之插入排序
    PAT 乙级 1044 火星数字 (20 分)
    PAT 甲级 1035 Password (20 分)
    PAT 甲级 1041 Be Unique (20 分)
    PAT 甲级 1054 The Dominant Color (20 分)
    PAT 甲级 1027 Colors in Mars (20 分)
    PAT 甲级 1083 List Grades (25 分)
    PAT 甲级 1005 Spell It Right (20 分)
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/6001604.html
Copyright © 2011-2022 走看看