URAL-1542 Autocompletion (字典序)

Autocompletion
Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

The Japanese are infinitely in love with machinery that surrounds them. They follow closely all technical innovations and try to use the most modern and clever of them. Den and Sergey have an ingenious plan: they want to create a text editor that will win the Japanese over. The most important feature of the editor will be the autocompletion function. If a user has typed first several letters of a word, then the editor will automatically suggest the most probable endings. 
Den and Sergey have collected a lot of Japanese texts. For each Japanese word they counted the number of times it was found in the texts. For the first several letters entered by a user, the editor must show no more than ten words starting with these letters that are most commonly used. These words will be arranged in the order of decreasing encounter frequencies. 
Help Sergey and Den to turn over the market of text editors. 

Input

The first line contains the number of words found in the texts  N (1 ≤   N ≤ 10  5). Each of the following  N lines contains a word  wi and an integer  ni separated with a space, where  wi is a nonempty sequence of lowercase Latin letters no longer than 15 symbols, and  ni (1 ≤  ni ≤ 10  6) is the number of times this word is encountered in the texts. The (  N + 2)th line contains a number  M (1 ≤   M ≤ 15000). In each of the next  M lines there is a word  ui (a nonempty sequence of lowercase Latin letters no longer than 15 symbols), which is the beginning of a word entered by a user. 

Output

For each of the  M lines, output the most commonly used Japanese words starting with  ui in the order of decreasing encounter frequency. If some words have equal frequencies, sort them lexicographically. If there are more than ten different words starting with the given sequence, output the first ten of them. The lists of words for each  ui must be separated by an empty line. 

Sample Input

input output
5
kare 10
kanojo 20
karetachi 1
korosu 7
sakura 3
3
k
ka
kar
kanojo
kare
korosu
karetachi

kanojo
kare
karetachi

kare
karetachi

题意:给n个单词,并给出词频,按照词频为第一优先级,字典序为第二优先级排序。之后m个询问,每次询问给出前缀,将前10个前缀匹配的单词输出,按照排序后的顺序。

解法:神奇的解法,先按询问建树,之后将排序后的单词按顺序查找,在结点处查询时记录查询的id和该结点被查询的次数,超过10次则跳过。最后统一输出。

自己码的莫名wa了,很奇怪,代码十分相似还是wa,最后贴别人代码过的。

#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
const int N=100005;
const int mod=1e9+7;

typedef struct Trie{
    Trie *next[26];
    bool v;
    vector<int> ans;
}Trie;

struct word{
    char w[16];
    int time;
}s[N];

Trie *root=(Trie *)malloc(sizeof(Trie));

void insert(char *str){
    int len=strlen(str);
    Trie *p = root,*q;
    for (int i=0; i<len; i++) {
        int id=str[i]-'a';
        if (p->next[id]==NULL) {
            q=(Trie *)malloc(sizeof(Trie));
            q->v=0;
            for (int j=0; j<26; j++)
                q->next[j]=NULL;
            p->next[id]=q;
        }
        p=p->next[id];
    }
    p->v=true;
}

void output(char *str) {
    Trie *p=root;
    int len=strlen(str);
    for (int i=0; i<len; i++) {
        int id=str[i]-'a';
        p=p->next[id];
    }
    for (int i=0; i<p->ans.size(); i++) {
        printf("%s\n",s[p->ans[i]].w);
    }
}

int find(char *str,int id){
    int len=strlen(str);
    Trie *p = root;
    for (int i=0; i<len; i++) {
        int id=str[i]-'a';
        p=p->next[id];
        if (p==NULL) return 0;
        if (p->ans.size()>=10) {
            continue;
        }
        p->ans.push_back(id);
    }
    return p->v;
}

void del(Trie *root){
    for (int i=0; i<26; i++) {
        if (root->next[i]!=NULL) {
            del(root->next[i]);
        }
    }
    free(root);
}


bool cmp(word a, word b) {
    if (a.time!=b.time) {
        return a.time>b.time;
    }
    return strcmp(a.w, b.w)<0;
}

char que[15005][15];

int main() {
    int n,m;
    cin>>n;
    for (int i=0; i<26; i++) {
        root->next[i]=NULL;
    }
    root->v=0;
    for (int i=0; i<n; i++) {
        scanf("%s %d",s[i].w,&s[i].time);
    }
    sort(s, s+n, cmp);
    cin>>m;
    for (int i=0; i<m; i++) {
        scanf("%s",que[i]);
        insert(que[i]);
    }
    for (int i=0; i<n; i++) {
        find(s[i].w, i);
    }
    for (int i=0; i<m; i++) {
        if (i) puts("");
        output(que[i]);
    }
    del(root);
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值