• 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 }
  • 相关阅读:
    NAVICAT 拒绝链接的问题
    .net垃圾回收-原理浅析
    C#中标准Dispose模式的实现
    Windbg调试托管代码
    C#泛型基础
    .Net垃圾回收和大对象处理
    C++ 小知识点
    C++之虚函数表
    C++之指针与引用,函数和数组
    C++之const关键字
  • 原文地址:https://www.cnblogs.com/rolight/p/3643861.html
Copyright © 2020-2023  润新知