背景:為了方便九宮格手機用戶發短信,希望在用戶按鍵時,根據提供的字典(給出字符串和頻數),給出各個階段最有可能要打的單詞。
題意: 首先給出的是字典,每個單詞有一個出現頻率。然後給出的是詢問,每個詢問有一個數字字符串,代表在手機上按了哪些鍵,以1結束。問按鍵的過程中最可能出現的單詞分別是哪些。
思路:搞了很久.......一開始總想著以字母為各結點如何建樹,詢問......還是太年輕了。
以手機8個鍵作為字典樹各節點,每個結點映射3-4對應的字母。每個結點存頻率最高的串,詢問的時候也可以方便的直接詢問了。
還是太年輕了.........理解題意為具有相同前綴的串的頻率是高的覆蓋低的........其實是疊加...........一直沒看出來。
題目是按照字典序升序給出字典的,所以可以把相同的前綴頻率相加,這樣只是插入一次了。
接下來就是基本字典樹的寫法了
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
char book[] = {"22233344455566677778889999"}; //映射
char str[1111][111];
int cou[1111][111];
struct trie {
trie *next[12];
char word[105];
int num;
trie() {
num = 0;
memset(next,0,sizeof(next));
memset(word,0,sizeof(word));
}
}*root;
void insert(char *key,int i) {
trie *p = root;
char tmp[105];
int ind = 0;
int j = 0;
while(key[j]) {
int t = book[key[j] - 'a'] - '0';
tmp[ind++] = key[j];
if(p->next[t] == NULL) {
p->next[t] = new trie();
}
p = p->next[t];
tmp[ind] = '\0';
if(p->num < cou[i][j]) {
p->num = cou[i][j];
strcpy(p->word,tmp);
}
j++;
}
}
void query(char *key) {
trie *p = root;
int flag = 0;
while(*key) {
int t = *key - '0';
if(p->next[t] == NULL || flag) { //用flag標記一下,有可能會有前一個單詞不存在,後面單詞存在字典中,此時應該輸出這個的
printf("MANUALLY\n");
key++;
flag = 1;
continue;
}
p = p->next[t];
printf("%s\n",p->word);
key ++;
}
}
void free(trie *p) { //釋放內存而已
for(int i=0; i<=9; i++) {
if(p->next[i] != NULL) free(p->next[i]);
}
delete p;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("D:\\hehe.txt","w",stdout);
#endif
int T,cnt;
cin >> T;
int casee = 1;
while(T --) {
root = new trie();
int n,i;
scanf("%d",&n);
for(i=0; i<n; i++) {
scanf("%s%d",str[i],&cnt);
int len = strlen(str[i]);
for(int j=0; j<len; j++) {
cou[i][j] = cnt;
}
}
for(i=1; i<n; i++) //相同前綴頻率相加,堆在一起算
for(int j=0; str[i][j] && str[i - 1][j]; j++) {
if(str[i][j] == str[i-1][j]) {
cou[i][j] += cou[i-1][j];
cou[i-1][j] = 0;
}
else break;
}
for(i=0; i<n; i++) {
insert(str[i],i);
}
printf("Scenario #%d:\n",casee ++);
int m;
scanf("%d",&m);
char str1[111],st[111];
for(i=0; i<m; i++) {
scanf("%s",st);
int len = strlen(st);
strncpy(str1,st,len-1);
str1[len-1] = '\0';
query(str1);
puts("");
}
puts("");
free(root);
}
return 0;
}