POJ1451 (字典树)

本题题意比较有意思,大概就是模拟手机输入法,先给你一个用户的词库,即每个单词出现的次数,这个时候再按照九键输入法给你一个数字序列,问你在输入这个序列的过程中,出现的字符串顺序,也就是对于每个数字序列,给出一个最有可能出现的字符串。
首先我们考虑,对于每个数字序列,我们都可以用一个string去映射,这样我们可以用一个map来保存每个数字序列对应的最有可能出现的字符串,可是我们怎么知道每个数字序列最有可能出现的字符串是哪个呢,首先我们对单词进行映射,把每个单词映射成数字序列,然后在插入的过程中,对于每一个前缀都更新一下这个前缀对应的map,最后查询的时候就可以直接输出了。

#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;

const int maxn = 1e6 + 10;
int tire[maxn][26];
int sum[maxn];
map<string, int> map1;
map<string, string> map2;
int alpha_to_int[30];
int tot;

void init() {
	for (int i = 0; i <= 17; ++i)
		alpha_to_int[i] = i / 3 + 2;
	alpha_to_int[18] = 7;
	for (int i = 19; i < 25; ++i)
		alpha_to_int[i] = (i - 1) / 3 + 2;
	alpha_to_int[25] = 9;
}

void insert(char* s, int num) {
	int len = strlen(s);
	int rt = 0;
	string temp_int = "", temp_alpha = "";
	for (int i = 0; i < len; ++i) {
		int id = s[i] - 'a';
		temp_int += alpha_to_int[id] + '0';
		temp_alpha += id + 'a';
		if (tire[rt][id] == 0)
			tire[rt][id] = ++tot;
		rt = tire[rt][id];
		sum[rt] += num;
		if (sum[rt] > map1[temp_int]) {
			map1[temp_int] = sum[rt];
			map2[temp_int] = temp_alpha;
		}
	}
}
int t, n, num;
char s[110];
int main() {
	int cnt = 1;
	init();
	for (scanf("%d", &t); t; --t) {
		map1.clear();
		map2.clear();
		scanf("%d", &n);
		tot = 0;
		for (int i = 0; i < n; ++i) {
			scanf("%s %d", s, &num);
			insert(s, num);
		}
		scanf("%d", &n);
		printf("Scenario #%d:\n", cnt++);
		for (int i = 0; i < n; ++i) {
			scanf("%s", s);
			int len = strlen(s);
			string temp = "";
			for (int j = 0; j < len - 1; ++j) {
				temp += s[j];
				if (!map2.count(temp))
					printf("MANUALLY\n");
				else
					printf("%s\n", map2[temp].c_str());
			}
			printf("\n");
		}
		printf("\n");
		for (int i = 0; i <= tot; ++i) {
			sum[i] = 0;
			for (int j = 0; j < 26; ++j)
				tire[i][j] = 0;
		}
	}
}

猜你喜欢

转载自www.cnblogs.com/wanshe-li/p/13382190.html