Encoded Barcodes HDU - 3724(字典树Trie 暴力也可过)

题目描述:给了n个字符串(仅含小写字母),m组查询,每组查询由k个8位数字组成,这8位数字组成8位二进制数代表一个字符(大写字母或小写字母)(输入的数值有5%的误差,原本这8个数只有a和2a,a代表0,2a代表1以此组成二进制串),如10.5   20.1   10.1   10.2    9.9   9.7   10.0   19.9去掉误差应该是10  20  10  10  10  10  10  20代表二进制01000001即十进制数65,这是A的ASCLL值,所以这8个数字代表A。求输入的这m组查询一共是多少字符串的前缀子串。至于误差处理我们想的是5%的误差绝对不是是它的1.5倍,所以如果一个数是它的1.5倍以上,则正确数值一定是它的2倍,相反如果小于1.5一定是它本身。而且所对应8位二进制最高位一定是0,否则它代表的不会是字母。

思路:场上是暴力过的,对于输入的每个字符串,先求出其所有的前缀子串,用map保存并记录其总共出现的次数。对于输入的m组查询求出其代表的字符串后直接在map中查找这个串出现的次数即可。赛后EF问我是用字典树写的吗,我说不是啊直接暴的,还被小小调侃了一下,场上能A就好嘛,干嘛笑话我不会字典树。赛后看了一下字典树,很好理解也确实挺好用的,所以又用字典树写了一遍。这样看来,这道题其实是一道很裸的字典树模板题。

两个版本代码如下:

暴力预处理记录所有子串及出现次数查询时直接找即可:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 100000 + 66;
const double eps = 1e-6;
int n, m, k;
double a[10];
int num[10];
map<string, int> mp;
char changes(){
    int cnt = 0;
    for(int i = 0; i < 8; ++i){
        cnt = cnt * 2 + num[i];
    }
    char ch = cnt;
    return ch;
}
int main(){
    while(~scanf("%d%d", &n, &m)){
        mp.clear();
        string str, tmp;
        int len;
        for(int i = 0; i < n; ++i){
            cin >> str;
            len = str.size();
            for(int l = 1; l <= len; ++l){
                tmp = str.substr(0, l);
                ++mp[tmp];
            }
        }
//        for(map<string, int> :: iterator it = mp.begin(); it != mp.end(); ++it){
//            cout << (*it).first << " " << (*it).second << endl;
//        }
        int ans = 0;
        while(m--){
           scanf("%d", &k);
           string tmp = "";
           char ch;
           bool ok = true;
           while(k--){
                scanf("%lf", &a[0]);
                num[0] = 0;
                for(int i = 1; i < 8; ++i){
                    scanf("%lf", &a[i]);
                    if(a[i] / a[0] > 1.5 - eps) num[i] = 1;
                    else num[i] = 0;
                }
                if(!ok) continue;
                ch = changes();
                if(!(ch >= 'a' && ch <= 'z')){
                    ok = false;
                }
                tmp += ch;
            }
            if(!ok) continue;
            ans += mp[tmp];
        }
        printf("%d\n", ans);
    }
    return 0;
}

Trie模板版本:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
const int maxn = 100000 + 66;
const double eps = 1e-6;
int n, m, k;
double a[10];
int num[10];
struct node{
    int value;
    struct node *son[26];
    node(){
        value = 0;
        memset(son, 0, sizeof son);
    }
}*root;
void build(node *root, string str){
    int len = str.size();
    int x;
    for(int i = 0; i < len; ++i){
        x = str[i] - 'a';
        if(root->son[x] == NULL){
            root->son[x] = new node();
        }
        root = root->son[x];
        ++root->value;
    }
}
int searchs(node *root, string str){
    int len = str.size();
    int x;
    for(int i = 0; i < len; ++i){
        x = str[i] - 'a';
        if(root->son[x] == NULL) return 0;
        root = root->son[x];
    }
    return root->value;
}
char changes(){
    int x = 0;
    for(int i = 0; i < 8; ++i){
        x = x * 2 + num[i];
    }
    return char(x);
}
int main(){
    while(~scanf("%d%d", &n, &m)){
        root = NULL;
        root = new node();
        string str;
        for(int i = 0; i < n; ++i){
            cin >> str;
            build(root, str);
        }
        bool ok;
        char ch;
        int ans = 0;
        while(m--){
            scanf("%d",&k);
            str = "";
            ok = true;
            while(k--){
                num[0] = 0; scanf("%lf", &a[0]);
                for(int i = 1; i < 8; ++i){
                    scanf("%lf", &a[i]);
                    if(a[i] / a[0] > 1.5 + eps) num[i] = 1;
                    else num[i] = 0;
                }
                ch = changes();
                if(!(ch >= 'a' && ch <= 'z')) ok = false;
                str += ch;
            }
            if(!ok) continue;
            ans += searchs(root, str);
        }
        printf("%d\n", ans);
    }
    return 0;
}

    原文作者:Trie树
    原文地址: https://blog.csdn.net/smwqd_yehua_cx/article/details/76408272
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞