题意加算法
题意加算法
这题要求我们模拟一下九键输入法输入数字推荐单词的算法,根据题意
原题传送
我们可以利用字典树来维护频率最高的前缀,来实现推荐,而那些频率不比其他同系列内单词高的前缀实际是没有意义的,例如
abe 5
abf 6
因为在223这个数字输入情况下,这两个长度为三且属于223,即为同一模块的,但是abe频率低,所以理论上它永远也没有用了(针对本题意),所以我们只需要维护每个数字对应的最常出现的字符即可,
在存字符串数量的时候要注意,因为是排好序的,所以我们只需要比较现在存的字符串和上一个字符串的相同前缀的累加到当前前缀上,然后把前一个清零即可,看看代码更加能明白
for(int i = 1; i < n; i++)//n个ĵ字符输入
for(int j = 0; s[i][j] && s[i - 1][j]; j++)//相同字符累加,上一个如果和下一个一样就一直累
{
//加,然后把原来的清除
if(s[i][j] == s[i - 1][j])
{
c[i][j] += c[i - 1][j];
c[i - 1][j] = 0;
}
else break;
}
然后存的过程中维护最频繁的前缀即可,
然后查询;
代码解析
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#define MAXM 55555
using namespace std;
int c[1005][105], e;
char s[1005][105];
char tmp[105];
char dic[] = "22233344455566677778889999";
struct Trie
{
int next[8];
int num;
char s[105];
void init ()
{
memset(next, 0, sizeof(next));
num = 0;
}
} trie[MAXM];
void make_trie (char *str, int id)
{
int i = 0, index, u = 0;
while(str[i])
{
index = dic[str[i] - 'a'] - '2';
if(!trie[u].next[index]) trie[u].next[index] = ++e;
u = trie[u].next[index];
if(c[id][i] > trie[u].num)
{
trie[u].num = c[id][i];
for(int j = 0; j <= i; j++) trie[u].s[j] = s[id][j];
trie[u].s[i + 1] = '\0';
}
i++;
}
}
void match(char *str)
{
int i = 0, index, u = 0, flag = 0;;
while(str[i] && str[i] != '1')
{
index = str[i] - '2';
u = trie[u].next[index];
if(trie[u].num == 0 || u == 0 || flag) printf("MANUALLY\n"), flag = 1;
else printf("%s\n", trie[u].s);
i++;
}
}
int main()
{
int T, n, p, m, cas = 0;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
memset(c, 0, sizeof(c));
for(int i = 0; i < n; i++)
{
scanf("%s%d", s[i], &p);//输入字符和数量
int len = strlen(s[i]);
for(int j = 0; j < len; j++) c[i][j] = p;//全部都存为P个,记录数据
}
for(int i = 1; i < n; i++)//n个ĵ字符输入
for(int j = 0; s[i][j] && s[i - 1][j]; j++)//相同字符累加,上一个如果和下一个一样就一直累
{
//加,然后把原来的清除
if(s[i][j] == s[i - 1][j])
{
c[i][j] += c[i - 1][j];
c[i - 1][j] = 0;
}
else break;
}
for(int i = 0; i < MAXM; i++)
trie[i].init();//初始化
e = 0;
for(int i = 0; i < n; i++)
make_trie(s[i], i);
scanf("%d", &m);
printf("Scenario #%d:\n", ++cas);
while(m--)
{
scanf("%s", tmp);
match(tmp);
printf("\n");
}
printf("\n");
}
return 0;
}