HDU 4287 Intelligent IME(字典树数组版)

Posted Blackops

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4287 Intelligent IME(字典树数组版)相关的知识,希望对你有一定的参考价值。

Intelligent IME

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4776    Accepted Submission(s): 2227

Problem Description
  We all use cell phone today. And we must be familiar with the intelligent English input method on the cell phone. To be specific, the number buttons may correspond to some English letters respectively, as shown below:
  2 : a, b, c    3 : d, e, f    4 : g, h, i    5 : j, k, l    6 : m, n, o    
  7 : p, q, r, s  8 : t, u, v    9 : w, x, y, z
  When we want to input the word “wing”, we press the button 9, 4, 6, 4, then the input method will choose from an embedded dictionary, all words matching the input number sequence, such as “wing”, “whoi”, “zhog”. Here comes our question, given a dictionary, how many words in it match some input number sequences?
 

 

Input
  First is an integer T, indicating the number of test cases. Then T block follows, each of which is formatted like this:
  Two integer N (1 <= N <= 5000), M (1 <= M <= 5000), indicating the number of input number sequences and the number of words in the dictionary, respectively. Then comes N lines, each line contains a number sequence, consisting of no more than 6 digits. Then comes M lines, each line contains a letter string, consisting of no more than 6 lower letters. It is guaranteed that there are neither duplicated number sequences nor duplicated words.
 

 

Output
  For each input block, output N integers, indicating how many words in the dictionary match the corresponding number sequence, each integer per line.
 

 

Sample Input
1
3 5
46
64448
74
go
in
night
might
gn
 

 

Sample Output
3
2
0

 

题目链接:HDU 4287

由于最近要学AC自动机的缘故,指针版的字典树虽然好写但是速度慢且容易爆内存,于是就膜了一下数组版的字典树,略微麻烦了一丢丢,但是可操作性比指针的高,速度比指针的快非常多……,于是就拿这题试验了一下,数组版字典树是用下标来替代指针的作用,而且空间都是预先分配好的,只要不把下标标向某一层,这一层就不会被用到,就相当于未出现,没有被分配内存。tot表示当前节点个数,显然一开始tot=1,因为有一个表头(对应于链表里的Nodelist *L),且表头的数组下标刚好是0,每一次分配就把L[tot]这一层的内容给初始化,再把这个连到L[now]->nxt[v]上即可。这题做法非常简单,就是问你每一个按键顺序可以分别打出下面几个字符串,显然把字典树结构体中加一个id表示当前是第几组按键,再把接下来的m个字符转换成对应的按键顺序再拿去查询,返回最后查到的那个id再把这个对应的按键次数+1即可。对了这个空间复杂度大概就开max_len * Tot_cnt就大概可以了,具体不清楚到底要开多少,反正暂时开这么多似乎题目都还可以过。话说把init作为成员函数里面还真是方便…………

代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=5010;
struct Trie
{
    int nxt[10];
    int id;
    inline void init()
    {
        CLR(nxt,0);
        id=-1;
    }
};
Trie L[N*7];
int tot,ans[N];
char s[10];
char change[10];

void init()
{
    L[0].init();
    tot=1;
    CLR(ans,0);
}
void update(char s[],int id)
{
    int now=0,len=strlen(s);
    for (int i=0; i<len; ++i)
    {
        int v=s[i]-‘0‘;
        if(!L[now].nxt[v])
        {
            L[tot].init();
            L[now].nxt[v]=tot++;
        }
        now=L[now].nxt[v];
    }
    L[now].id=id;
}
int Find(char s[])
{
    int now=0;
    int len=strlen(s);
    for (int i=0; i<len; ++i)
    {
        int v=s[i]-‘0‘;
        if(!L[now].nxt[v])
            return -1;
        now=L[now].nxt[v];
    }
    return L[now].id;
}
inline int getid(const char &x)
{
    if(x>=‘a‘&&x<=‘c‘)
        return 2;
    else if(x>=‘d‘&&x<=‘f‘)
        return 3;
    else if(x>=‘g‘&&x<=‘i‘)
        return 4;
    else if(x>=‘j‘&&x<=‘l‘)
        return 5;
    else if(x>=‘m‘&&x<=‘o‘)
        return 6;
    else if(x>=‘p‘&&x<=‘s‘)
        return 7;
    else if(x>=‘t‘&&x<=‘v‘)
        return 8;
    else
        return 9;
}
int main(void)
{
    int tcase,n,m,i;
    scanf("%d",&tcase);
    while (tcase--)
    {
        init();
        scanf("%d%d",&n,&m);
        for (i=0; i<n; ++i)
        {
            scanf("%s",s);
            update(s,i);
        }
        for (i=0; i<m; ++i)
        {
            scanf("%s",s);
            int len=strlen(s);
            for_each(s,s+len,[](char &c){c=getid(c)+‘0‘;});
            int indx=Find(s);
            if(indx!=-1)
                ++ans[indx];
        }
        for_each(ans,ans+n,[&](const int &c){printf("%d\n",c);});
    }
    return 0;
}

以上是关于HDU 4287 Intelligent IME(字典树数组版)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4287 Intelligent IME(map运用)

HDU 4287 Intelligent IME(字典树数组版)

Intelligent IME HDU - 4287 字典树

HDU4287

background intelligent transfer service怎么关闭

background intelligent transfer service启动问题