您的位置:首页 > 其它

hdu 3724 Encoded Barcodes(字典树)

2015-09-11 17:08 525 查看


Encoded Barcodes

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1688 Accepted Submission(s): 587



Problem Description

All the big malls need a powerful system for the products retrieval. Now you are employed design a sub-system: reading the barcodes and return the matching products.

A barcode is an optical machine-readable representation of data, which shows certain data on certain products. A barcode consists of a series of bars with different widths. In our system, the barcodes have been scanned and the widths have been recorded. Every
consecutive eight bars are considered as representing the ASCII code of a character, each bar for each bit. Ideally, there should be only two kinds of widths in the eight bars, and the width of the wider bar is twice of the narrower. The wider bar indicates
1, while the narrower indicates 0. However, due to the inaccuracy of printing and scanning, there will be an error of at most 5%. That is, if the pretended exact width is x, you may get a value in the range [0.95x, 1.05x].

For example, the width sequence "10.0 20.0 10.0 10.0 10.0 10.0 10.0 20.0" is a valid barcode of our system, and it means (01000001)2, which is (65)10 and the corresponding character is "A". Note that "10.5 20.1 10.1 10.2 9.9 9.7 10.0 19.9"
is also a valid barcode representing the same letter.

You are given the names of all the products and many queries. Every name contains lower-case letters only, and the length is no more than 30. The queries are represented as barcodes. For each query, you should decode it to a string S, and report the amount
of products whose prefix is S. For the output may be very large, you only need to output the sum of all the queries for each case.



Input

There are several test cases in the input. The first line of each case contains two integers N and M (1 <= N <= 10000, 1 <= M <= 2000), indicating the number of products and queries. Then N lines follow, indicating the names of the products. Note that the names
may be duplicated. Then M query blocks follow. The first line of each query block is an integer K (0 < K <= 30) indicating the length of the query, then K lines follow, each line contains 8 positive float numbers, indicating the barcode for each character.

You can assume that the barcodes are always valid, and always represent lower-case letters.



Output

Output one line for each test case, indicating the sum of all the query results as described above.



Sample Input

4 3
apple
apple
avatar
book
1
1 2 2 1 1 1 1 2
2
1 2 2 1 1 1 1 2
10.1 20.1 19.9 20.0 10.2 9.8 9.9 10.0
1
1 2 2 1 1 1 2 2




Sample Output

5

HintThere is only one test case. The first query is "a", and the answer is 3. The second query is "ap", and the answer is 2. The third query is "c", and the answer is 0. So the total sum is 3+2+0 = 5.




Source

2010 Asia Tianjin Regional Contest



题意:有N个产品,名称由小写字母组成,有M个询问,每个询问先来一个K,再输入K个条形码,条形码有8个值,每个数是原来的【0.95,1.05】倍,8个数之中最大数是最小数的两倍,即这8个数只有x和2*x,x代表0,2*x代表1,每个条形码代表1个小写字母,这K个条形码连成连续的K个字母作为前缀,统计这个前缀是多少个产品名的前缀(重复的算多次),输出M个询问的统计个数和。

题解:先建一颗字典树,再查询。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>

using namespace std;

struct Trie {
    int num;
    struct Trie *Next[26];
    Trie() {
        for(int i=0; i<26; i++) {
            Next[i]=NULL;
        }
        num=1;
    }
};

char s[110];

void build(Trie *T) {
    Trie *Tt=T;
    int len=strlen(s);
    int i=0;
    while(i<len) {
        int x=s[i]-'a';
        if(Tt->Next[x]==NULL) {
            Tt->Next[x]=new Trie;
        } else {
            Tt->Next[x]->num++;
        }
        Tt=Tt->Next[x];
        i++;
    }
}

int serch(Trie *T) {
    Trie *Tt=T;
    int len=strlen(s);
    int i=0;
    while(i<len) {
        int x=s[i]-'a';
        if(Tt->Next[x]==NULL)return 0;
        Tt=Tt->Next[x];
        i++;
    }
    return Tt->num;
}

int n,m;

int main() {
    //freopen("test.in","r",stdin);
    while(~scanf("%d%d",&n,&m)) {
        Trie *T=new Trie;
        for(int i=0; i<n; i++) {
            scanf("%s",s);
            build(T);
        }
        double a[10];
        int ans=0;
        for(int i=0; i<m; i++) {
            int k;
            scanf("%d",&k);
            for(int l=0; l<k; l++) {
                double Max=0;
                for(int j=0; j<8; j++) {
                    scanf("%lf",&a[j]);
                    Max=max(Max,a[j]);
                }
                int asc=0;
                for(int j=0; j<8; j++) {
                    if(a[j]>=Max*0.95/1.05)//判断0,1
                        asc+=(1<<(7-j));
                }
                s[l]=asc;
            }
            s[k]=0;
            ans+=serch(T);
        }
        printf("%d\n",ans);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: