English Game NBUT - 1222 (DP+trie/字符串hash)

题意:

这个英语游戏是一个简单的英语单词连接游戏。

规则如下:一本词典中有N个英语单词,每个单词都有自己的权重v。如果使用相应的词,则有一个权重。现在有一个目标字符串X。你必须在字典里挑选一些单词,然后把它们连接到X表中。同时,你选择的词的总权重一定是最大的。

输入

有几个测试用例。对于每个试验,首先给出N(1<=N<=1000)和X(X的长度不大于10000)。接着是N行。每行包含一个单词wi(长度不大于30)及其权重。每个单词都由小写字母组成。字典里没有两个词是相同的。

输出

对于每个测试用例,输出最大的和权重,如果不能形成字符串X,则输出-1。

 

题解:定义f[i]为已经选到第i个位置所能凑到的最大价值,则f[i]的所有子集及对于一个当前字符串而言后缀中所有包含单词的及集合。如果数据小的话其实到这已经可以做了,如果数据大的话需要利用字符串hash或者字典树来判断当前后缀是否是一个单词。

AC代码:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1010;
int n;
string s;
int son[N*30][30],idx;
int f[N*30],w[N*30];

void insert(string a,int b){
	int p=0;
	//cout<<a<<"****"<<endl;
	for(int i=0;i<a.size();i++){
		int k=a[i]-'a';
		if(!son[p][k]) son[p][k]=++idx;
		p=son[p][k];
	}
	//cout<<p<<"****"<<endl;
	w[p]=b;
} 


int main(){
	while(cin>>n>>s){
		memset(son,0,sizeof son);
		idx=0;
		memset(w,-1,sizeof w);
		memset(f,-1,sizeof f);
		
		while(n--){
			string x;
			int w;
			cin>>x>>w;
			reverse(x.begin(),x.end());
			insert(x,w);
		}
		
		f[0]=0;
		for(int i=1;i<=s.size();i++){
			int p=0;
			for(int j=i;j>=1&&j>=i-30;j--){
				int k=s[j-1]-'a';
				//cout<<s[j-1]<<"******"<<endl;
				if(!son[p][k])break;
				p=son[p][k];
				if(w[p]!=-1&&f[j-1]!=-1){
					//cout<<i<<" "<<w[p]<<endl;
					f[i]=max(f[i],f[j-1]+w[p]);
				}
			}
		}
		
		if(f[s.size()])cout<<f[s.size()]<<endl;
		else cout<<-1<<endl;
	}
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值