AOJ 673 聪明的输入法

众所周知,讯飞输入法具备强大的学习功能,对于用户来说,感觉输入法像一个会学习的机器人,比如,当用户第一次输入“sxl”,输入法第一个提示“少写了”,
如果用户选择“睡醒了”,当第二次用户再输入“sxl”的时候,“睡醒了”这个词就会出现在比较靠前的位置,神奇吧,输入法就像一个小孩子,在你的指导下慢慢学会每个拼音的含义。
现在让我们一起来实现下这个神奇的功能吧,为方便起见,我们假设用户是美国籍的(仅输入小写英语字母),每当该用户输入一个单词时,请输出和该用户输入习惯最为匹配的单词(以该单词为前缀的输入频率最高的单词),如果有多个则输出字典序最小的,如果没有的话,则直接输出该单词。

就是校赛的那道字典树模板提啦。当初我是用猥琐的二分水过的,事实证明那其实是bo神忘记加了一组可以卡掉我代码的数据而已,事实上这种数据还很好构造o(╯□╰)o

正好最近在学习字典树,就用字典树重写了一遍,记录以一个节点为根节点的子树中频率最大的节点,应该是比较基础的字典树题目啦

一开始按照bo神教我的写法是2.1s,后来发现只要把STL的stack改成自己模拟的就只要900ms了,看来STL不能乱用啊,估计是我把stack声明在循环体里面,每次循环的时候都要new和析构一下,消耗了许多时间吧。

最后Orz一下Wzy的511ms

 1 #include <cstdio>
 2 #include <sstream>
 3 #include <fstream>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 #include <map>
 8 #include <cctype>
 9 #include <ctime>
10 #include <set>
11 #include <climits>
12 #include <vector>
13 #include <queue>
14 #include <stack>
15 #include <cstdlib>
16 #include <cmath>
17 #include <string>
18 #include <list>
19  
20 #define INPUT_FILE "in.txt"
21 #define OUTPUT_FILE "out.txt"
22  
23 using namespace std;
24  
25 typedef long long LL;
26 const int INF = INT_MAX / 2;
27  
28 void setfile() {
29     freopen(INPUT_FILE,"r",stdin);
30     freopen(OUTPUT_FILE,"w",stdout);
31 }
32  
33 const int maxn = 100000;
34 const int maxlen = 11;
35 const int maxnode = maxn * (maxlen - 1);
36 const int sigma_size = 26;
37  
38 char buf[maxn + 1][maxlen];
39  
40 struct tnode {
41     int next[sigma_size],times,most,val,from;
42     char letter;
43 };
44  
45 tnode node[maxnode];
46 int path[15],top = 0;
47 int sz;
48  
49  
50 int main() {
51     int n; scanf("%d",&n);
52     //初始化trie树
53     sz = 1;
54     memset(&node[0],0,sizeof(tnode));
55     node[0].from = -1;
56     //处理输入
57     for(int i = 1;i <= n;i++) {
58         scanf("%s",buf[i]);
59         //插入trie树
60         int len = strlen(buf[i]),u = 0;
61         top = 0;
62         for(int j = 0;j < len;j++) {
63             path[top++] = u;    //记录路径
64             int c = buf[i][j] - 'a';
65             if(node[u].next[c] == 0) {
66                 memset(&node[sz],0,sizeof(tnode));
67                 node[sz].letter = c;
68                 node[sz].from = -1;
69                 node[sz].most = sz;
70                 node[u].next[c] = sz++;
71             }
72             u = node[u].next[c];
73         }
74         if(node[u].times == 0) {
75             node[u].val = i;
76         }
77         node[u].times++;
78         //输出单词
79         printf("%s
",buf[node[node[u].most].val]);
80         //更新节点自身
81         if(node[u].times >= node[ node[u].most ].times) {
82             node[u].most = u; node[u].from = -1;
83         }
84         while(top > 0) {
85             //向上依次更新每一个经过的节点的最大子树
86             int fa = path[--top];
87             int fmost = node[fa].most;
88             int umost = node[u].most;
89             if(node[umost].times > node[fmost].times //子节点的最大频率值比父节点的大
90                     || (node[umost].times == node[fmost].times && (node[u].letter <= node[fa].from))) //频率相等但是字典序靠前
91             {
92                 node[fa].most = umost;
93                 node[fa].from = node[u].letter;
94             } else break;
95             u = fa;
96         }
97     }
98     return 0;
99 }
原文地址:https://www.cnblogs.com/rolight/p/3643861.html