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;
    }
    
  • 相关阅读:
    xCHM 1.11
    Fluxbox 1.0 RC 3
    Money Manager Ex:个人理财软件
    K3b 1.0 变化了什么?
    Kbfx:KMenu 的替换品
    Semantik:思想导图绘制软件
    新手入门:了解邮件服务与相关协议
    用 GDI 操作 EMF 文件[2]: PlayEnhMetaFile、DeleteEnhMetaFile
    WinAPI: WritePrivateProfileString、GetPrivateProfileString 简单读写 Ini 文件
    一毫米等于多少像素? GetDeviceCaps
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/6001604.html
Copyright © 2011-2022 走看看