poj 1451 T9 字典树

本文介绍了一种利用字典树构建手机短信预测系统的算法,通过整合单词频率和数字键盘映射,实现用户在输入过程中预测并推荐可能要输入的词汇,提升手机短信输入效率。

题目链接:poj.org/problem?id=1451

题目背景:为了方便手机用户发短信,希望在用户按键时,根据每个词出现的频数,给出每个阶段最有可能要打的词。

PS:相同的前缀频数要相加计算。

题目大意:有不同的几组测试样例,每个测试样例中有w个词及每个词出现的频数,然后是p组要打的词,按1键表示结束输入。要求输出按到每个键时最可能要打的词。


解题思路:

根据每个单词建立一棵“单词字典树”(A树), 附加域记录每个字母出现的频数。再根据“单词字典树”建立一棵“数字字典树”(B树),附加域里记录最大频数及对应的单词下标。

下面我们细细地研究下:首先说,按每个词去建字典树应该都会。现在呢,要在建A树的同时建起B树来。所以我们需要一个映射,一个从字母到数字键盘的映射,根据这个映射关系去更新B树。比如,在“hell”和“hello”之后出现了“idea”,此时,在A树中只是新加进来个词而已,而在B树中则不然,因为idea对应的数字键为4332,和前面的hell的前两位43是相同的,因此,在B树中更新时,4和4之后3的频数值将从hell和hello的7改为idea的8,下标值也将从hello的下标2改为idea的下标3。如图:


这样,当按键时,就可以直接从B树中读取出下标来进行输出了。


OK,具体代码如下(用时47MS):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define maxn 0x0400

typedef struct word {
	int p;	// probability value
	struct word* next[26];
}word, *W;

typedef struct dig {
	int p;	// probability value
	int w;	// word's sub in dict[]
	struct dig* next[10];
}dig, *D;

// From alpha to digit
int atod[26] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5,
	5, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9};
char dict[maxn][0x80];
W wroot = NULL;
D droot = NULL;

inline W getW() {
	int i;
	W p = (W)malloc(sizeof(word));
	p->p = 0;
	for (i = 0; i < 26; i++) {
		p->next[i] = NULL;
	}
	return p;
}
inline D getD() {
	int i;
	D p = (D)malloc(sizeof(dig));
	p->p = 0;
	for (i = 0; i < 10; i++) {
		p->next[i] = NULL;
	}
	return p;
}

void delw(W p) {
	int i;
	for (i = 0; i < 26; i++) {
		if (p->next[i]) {
			delw(p->next[i]);
		}
	}
	free(p);
}

void deld(D p) {
	int i;
	for (i = 0; i < 10; i++) {
		if (p->next[i]) {
			deld(p->next[i]);
		}
	}
	free(p);
}

int main() {
	int cs, x, n, i, p, j, q;
	char s[0x80];
	scanf("%d", &cs);
	for (x = 1; x <= cs; x++) {
		W wp = wroot = getW();
		D dp = droot = getD();
		scanf("%d", &n);
		for (i = 1; i <= n; i++) {
			scanf("%s %d", s, &p);
			strcpy(dict[i], s); // 存下所有的词
			wp = wroot;
			dp = droot;
			for (j = 0; s[j]; j++) {
				int pos = s[j] - 97;
				if (wp->next[pos] == NULL) {
					wp->next[pos] = getW();
				}
				if (dp->next[atod[pos]] == NULL) {
					dp->next[atod[pos]] = getD();
				}
				wp = wp->next[pos];
				wp->p += p;
				dp = dp->next[atod[pos]];
				// 下面是根据A树建B树的过程
				if (wp->p > dp->p) {
					dp->p = wp->p; // 更新probability值
					dp->w = i; // 更新对应单词的下标
				}
			}
		}
		scanf("%d", &q);
		printf("Scenario #%d:\n", x);
		while (q--) {
			scanf("%s", s);
			dp = droot;
			for (i = 0; s[i] != 49; i++) {
				int pos = s[i] - 48;
				if (dp) { // 如果有这种按键方式的词
					dp = dp->next[pos];
					if (dp) {
						// 可能按到上一个键时还有
						// 到这个键时就没有了
						for (j = 0; j <= i; j++) {
							putchar(dict[dp->w][j]);
						}
					} else {
						printf("MANUALLY");
					}
				} else {
					printf("MANUALLY");
				}
				printf("\n");
			}
			printf("\n");
		}
		printf("\n");
		delw(wroot);
		deld(droot);
	}
	return 0;
}


在此呢,可以单独写个空间申请以加快速度(连free也省了,用时16MS):

word WS[100000];
dig DS[100000];
inline void init() {
	WTOP = DTOP = 0;
}

inline W getW() {
	int i;
	W p = &WS[WTOP++];
	p->p = 0;
	for (i = 0; i < 26; i++) {
		p->next[i] = NULL;
	}
	return p;
}
inline D getD() {
	int i;
	D p = &DS[DTOP++];
	p->p = 0;
	for (i = 0; i < 10; i++) {
		p->next[i] = NULL;
	}
	return p;
}

正所谓,要哈希呢,就彻头彻尾的哈希吧(用时0MS):

#include <stdio.h>

char *as = "abcdefghijklmnopqrstuvwxyz", ai[128];
char *ah = "22233344455566677778889999", di[128];

char ls[1000][101];
int w, d, l;
int wb[99927][26], wp[99927];
int db[33309][8], dp[33309], dl[33309];

void ins(char* s, int p) {
	int i, j, wt, dt;
	for (i = wt = dt = 0; s[i]; i++) {
		if (!wb[wt][ai[s[i]]]) {
			wb[wt][ai[s[i]]] = ++w;
			wp[w] = 0;
			for (j = 0; j < 26; j++)
				wb[w][j] = 0;
		}

		if (!db[dt][di[s[i]]]) {
			db[dt][di[s[i]]] = ++d;
			dp[d] = 0;
			for (j = 0; j < 8; j++)
				db[d][j] = 0;
		}

		wt = wb[wt][ai[s[i]]];
		dt = db[dt][di[s[i]]];

		wp[wt] += p;
		if (wp[wt] > dp[dt]) {
			dp[dt] = wp[wt];
			dl[dt] = l;
		}
	}

	sprintf(ls[l++], s);
}

void tap(char* s) {
	int i, j, dt;
	for (i = dt = 0; s[i] > '1'; i++) {
		if (!db[dt][di[s[i]]])
			break;

		dt = db[dt][di[s[i]]];

		for (j = 0; j <= i; j++)
			putchar(ls[dl[dt]][j]);
		puts("");
	}

	for (; s[i] > '1'; i++)
		puts("MANUALLY");
}

int main() {
	int c, n, p, i;
	char s[128];

	for (p = 0; as[p]; p++) {
		ai[as[p]] = p;
		di[as[p]] = ah[p] - '2';
		di[ah[p]] = ah[p] - '2';
	}

	scanf("%d", &c);
	for (i = 1; i <= c; i++) {
		w = d = l = 0;
		for (p = 0; p < 8; p++) db[0][p] = wb[0][p] = 0;
		for (; p < 26; p++) wb[0][p] = 0;
		printf("Scenario #%d:\n", i);

		scanf("%d", &n);
		while (n--) {
			scanf(" %s %d", s, &p);
			ins(s, p);
		}

		scanf("%d", &n);
		while (n--) {
			scanf(" %s", s);
			tap(s);
			puts("");
		}
		puts("");
	}

	return 0;
}


内容概要:本研究聚焦于绿电直连型电氢氨园区的优化运行,提出一种集成绿色电力直接供给、电解水制氢及氢气合成氨工艺的综合能源系统架构。通过建立包含风光发电、电解槽、氨合成反应器、储氢罐、电网交互及多类型负荷在内的系统模型,综合考虑绿电直供优先、能量梯级利用与多能互补原则,构建以系统综合运行成本最小化为目标的优化调度模型。研究采用Matlab与Python工具进行算法求解和仿真分析,利用实际气象与负荷数据完成案例验证,评估了不同运行策略下系统的经济性、可再生能源消纳能力与碳减排效益,为新型电氢氨一体化园区的规划与运行提供了理论依据和技术支撑。; 适合人群:具备一定电力系统、新能源或化工背景的研究生、科研人员及从事综合能源系统规划与优化工作的工程技术人员。; 使用场景及目标:①用于科研学习,理解电-氢-氨多能转换系统的建模与优化方法;②为工业园区的低碳化、智能化改造提供技术参考与决策支持;③作为开发类似综合能源管理系统的理论基础。; 阅读建议:此资源包含完整的模型代码、数据与论文,使用者应结合代码仔细研读论文中的模型构建部分,重点关注目标函数与约束条件的设计逻辑,并尝试修改参数进行仿真,以深入掌握优化算法在实际系统中的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值