【解题报告】POJ1451-T9 Trie+BFS

这道题看着很复杂,其实感觉就是建字典树,然后bfs一遍,然后bfs的队列需要用优先队列来维护出现的频率,每当到新的一层的时候,只输出频率最大的那个,然后把所有这一层的都扩展到下一层,以此类推。

同时最后如果在某一层找不到往下走的时候,后边的就直接输出剩余层数的MAMUALLY。

另外,最好优化下各种空间,一开始卡空间,卡着卡着就过去了hhh

AC代码:

#include <string>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=1e4;
int trie[maxn][26],tot=1;
int fre[maxn];
string hhash[10]={"","next","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
void init()
{
	tot=1;
	memset(fre,0,sizeof(fre));
	memset(trie,0,sizeof(trie));
}
void insert(string str,int f)
{
	int len=str.size(),p=1;
	for(int k=0;k<len;k++){
		int ch=str[k]-'a';
		if(trie[p][ch]==0) trie[p][ch]=++tot;
		p=trie[p][ch];
		fre[p]+=f;
	}
}
struct node{
	int f;
	int level;
	int p;
	string s;
	node (int _f,int _level,int _p,string _s)
	{
		f=_f;
		level=_level;
		p=_p;
		s=_s;
	}
	bool operator < (const node& x) const
	{
		if(level!=x.level) return level>x.level;
		return f<x.f;
	}
};
void bfs(string s)
{
	string ans="";
	priority_queue<node> q;
	q.push(node(0,0,1,""));
	int level=0;
	while(!q.empty()){
		node temp=q.top();q.pop();
		if(temp.level==s.size()) return;
		int opt=s[temp.level]-'0';
		level=temp.level;
		string sopt=hhash[opt];
		if(level==0){
			for(int i=0;i<sopt.size();i++){
				if(trie[temp.p][sopt[i]-'a']!=0)
				q.push(node(fre[trie[temp.p][sopt[i]-'a']],temp.level+1,trie[temp.p][sopt[i]-'a'],temp.s+sopt[i]));
			}
			continue;
		}
		if(ans.size()<temp.level){
			ans=temp.s;
			cout<<ans<<endl;
		}
		for(int i=0;i<sopt.size();i++){
			if(trie[temp.p][sopt[i]-'a']!=0)
			q.push(node(fre[trie[temp.p][sopt[i]-'a']],temp.level+1,trie[temp.p][sopt[i]-'a'],temp.s+sopt[i]));
		}
	}
	for(int i=level+1;i<s.size();i++) 
		cout<<"MANUALLY"<<endl;
	return;
}
int main()
{
	int t;cin>>t;
	for(int kcase=1;kcase<=t;kcase++){
		int n,m;cin>>n;
		init();
		for(int i=1;i<=n;i++){
			string str;int f;
			cin>>str>>f;
			insert(str,f);
		}
		cout<<"Scenario #"<<kcase<<":"<<endl;
		cin>>m;
		for(int i=1;i<=m;i++){
			string s;cin>>s;
			bfs(s);
			cout<<endl;
		}
		cout<<endl;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值