HDU 1298 - T9(trie树)

题目链接 HDU1298

【题意】给出n(<=1000)个单词以及其出现概率值,每个单词的出现概率又是所有到这个位置的前缀之和,比如

or 2,np 1,nh 3,则串n出现概率为1+3,nh为3,np为1,o为2,or为2;然后求出每次输入手机键盘按钮时对应的概率最大的子串(不一定要出现的字符串,他们前缀都可以)。

【分析】一开始题意理解错了,以为概率为路径之和,知道题意后,还是蛮好写的,只要把字典树的查询改一下,用dfs完成,每次控制下可以查询的字符串(手机键盘数字对应的3,4个字母)就可以暴搜了。

#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
const int INF = 0x3f3f3f3f, MAXN = 1010;
int tree[MAXN<<5][30], val[MAXN<<5], cnt;

void init()
{
	clc(tree[0],-1);
	cnt = 1;
}
void insert(const char *s, int v)
{
	int u = 0, n = strlen(s);
	rep(i,0,n)
	{
		int c = s[i]-'a';
		if(-1 == tree[u][c])
		{
			clc(tree[cnt],-1);
			val[cnt] = 0;
			tree[u][c] = cnt++;
		}
		u = tree[u][c];
		val[u] += v;
	}
}
void get_num(int &si, int &len, int num)
{
	if(num <= 6)
	{
		si = (num-2)*3;
		len = 3;
		return;
	}
	if(7 == num)
	{
		si = 15;
		len = 4;
		return;
	}
	if(8 == num)
	{
		si = 19;
		len = 3;
		return;
	}
	si = 22, len = 4;
}
char pt[110], ans[110];
int mx;
void query(char *s, int u, int cnt, int len)
{
	if(cnt == len)
	{
		if(mx < val[u])
		{
			strcpy(ans,pt);
			mx = val[u];
		}
		return;
	}
	//得到按键对应的字母
	int si, n;
	get_num(si,n,s[cnt]-'0');
	rep(i,0,n)
	{
		int c = si+i;
		pt[cnt] = c+'a', pt[cnt+1] = 0;
		if(-1 == tree[u][c]) continue;
		query(s,tree[u][c], cnt+1, len);
	}
	return;
}
int main()
{
#ifdef SHY
	freopen("e:\\1.txt", "r", stdin);
	//freopen("e:\\out.txt","w",stdout);
#endif
	int t, count = 0;
	scanf("%d%*c", &t);
	while(t--)
	{
		int n, v;
		char s[110];
		scanf("%d%*c", &n);
		init();
		rep(i,0,n)
		{
			scanf("%s %d%*c",s, &v);
			insert(s,v);
		}
		int m;
		scanf("%d%*c", &m);
		printf("Scenario #%d:\n", ++count);
		rep(i,0,m)
		{
			scanf("%s", s);
			int len = strlen(s);
			s[len-1] = 0;
			bool end = false;
			rep(i,1,len)
			{
				if(!end)
				{
					mx = 0;
					query(s,0,0,i);
					if(mx)
						puts(ans);
					else
						puts("MANUALLY"), end = true;
				}
				else
					puts("MANUALLY");
			}
			putchar('\n');
		}
		putchar('\n');
	}
	return 0;
}

 

    原文作者:Trie树
    原文地址: https://blog.csdn.net/u012760629/article/details/41526361
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞