标签:using 产生 eof alt 频率 family 前缀 rcp 个数
题意 : 给你 w 个单词以及他们的频率,现在给出模拟 9 键打字的一串数字,要你在其模拟打字的过程中给出不同长度的提示词,出现的提示词应当是之前频率最高的,当然提示词不需要完整的,也可以是 w 个单词出现最多次数的前缀。
分析 : 利用字典树存储这 w 个单词,然后给每一个结点的权值赋上其单词出现频率,接下来的工作就简单多了,只要暴力枚举模拟输入的数字键盘可能产生的单词组合,然后保存频率最高的那个即可!
#include<string.h> #include<stdio.h> #include<malloc.h> #include<iostream> #include<algorithm> #include<map> using namespace std; const int maxn = 27; int tot = 0, n, m; const int INF = 0x3f3f3f3f; char mp[][5]{ ///模拟数字键盘,因为是从2开始,所以0和1都赋值上一个‘@‘代表空 {‘@‘,‘@‘,‘@‘,‘@‘,‘@‘}, {‘@‘,‘@‘,‘@‘,‘@‘,‘@‘}, {‘a‘,‘b‘,‘c‘,‘@‘,‘@‘}, {‘d‘,‘e‘,‘f‘,‘@‘,‘@‘}, {‘g‘,‘h‘,‘i‘,‘@‘,‘@‘}, {‘j‘,‘k‘,‘l‘,‘@‘,‘@‘}, {‘m‘,‘n‘,‘o‘,‘@‘,‘@‘}, {‘p‘,‘q‘,‘r‘,‘s‘,‘@‘}, {‘t‘,‘u‘,‘v‘,‘@‘,‘@‘}, {‘w‘,‘x‘,‘y‘,‘z‘,‘@‘} }; struct Trie { Trie *Next[maxn]; int v; inline void init(const int val){ this->v = val; for(int i=0; i<maxn; i++) this->Next[i] = NULL; } }; Trie *root; void CreateTrie(char *str, int val) { int len = strlen(str); Trie *p = root, *tmp; for(int i=0; i<len; i++){ int idx = str[i]-‘a‘; if(p->Next[idx] == NULL){ tmp = (Trie *)malloc(sizeof(Trie)); tmp->init(val); p->Next[idx] = tmp; }else (p->Next[idx]->v) += val;///赋上频率权值 p = p->Next[idx]; } } inline void DelTrie(Trie *T) { if(T == NULL) return ; for(int i=0; i<maxn; i++){ if(T->Next[i] != NULL) DelTrie(T->Next[i]); } free(T); return ; } char str[111], ans[111], now[111]; int tmp, MaxVal; void DFS(int pos, int len, Trie *NOD) { if(pos == len){///递归出口,看看频率是否更优,更新答案 if(NOD->v > MaxVal){ strcpy(ans, now); MaxVal = NOD->v; } return ; } int idx = str[pos]-‘0‘; for(int i=0; mp[idx][i]!=‘@‘; i++){///枚举这个数字建的所有字母,遇到‘@‘结束 int id = mp[idx][i] - ‘a‘; if(NOD->Next[id]){ ///如果字典树关于这个字母的节点不为空的话,则进一步搜索 now[pos] = mp[idx][i];///now是保存一下暂时现在构造出来的字符串,以便更新 now[pos+1] = ‘\0‘; DFS(pos+1, len, NOD->Next[id]);///进一步搜索 } } } int main(void) { int nCase; scanf("%d", &nCase); for(int Case=1; Case<=nCase; Case++){ root = (Trie *)malloc(sizeof(Trie)); root->init(0); scanf("%d", &n); int tmpVal; for(int i=0; i<n; i++){ scanf("%s %d", str, &tmpVal); CreateTrie(str, tmpVal); } printf("Scenario #%d:\n", Case); scanf("%d", &m); for(int i=0; i<m; i++){ scanf("%s", str); int len = strlen(str); for(int j=1; j<len; j++){///枚举长度 MaxVal = -INF; DFS(0, j, root); if(MaxVal == -INF) puts("MANUALLY"); else puts(ans); } puts(""); }puts(""); DelTrie(root); } return 0; }
标签:using 产生 eof alt 频率 family 前缀 rcp 个数
原文地址:http://www.cnblogs.com/Rubbishes/p/7608802.html