HDU_3724_Encoded Barcodes(字典树)

题型:字符串


题意:

      n个字符串,m次操作,每次操作刷k次条形码。

     条形码有宽度,分为窄码和宽码,二者宽度大致为二倍,误差不大于5%。

     每个条形码代表一个ASCII码,窄码为0,宽码为1,刷一次可以得到一个字母,每次操作,可以获得对应的k长度的字符串,然后去n个字符串中找具有相同前缀的字符串的个数。

     问最终共有查询出的字符串的总数。


分析:

      由于条形码的宽度有误差,在判断宽窄的时候,先找出最窄的宽度,然后看,如果当前的宽度与最窄宽度之差与最窄宽度的比小于20%,就可以认为当前宽度为0,否则为1.

      由于有10^4个字符串,所以需要降低查找时间,采用字典树处理即可。


代码:

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

#define inf 1e+12
#define eps 1e-8
#define M 100010
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;

class Trie_tree {
    struct node {
        int next[26],ptr,num;
        void init() {
            ptr=-1;
            num=0;
            mt(next,0);
        }
    } s[M];
    int ls,p;
    int f(char c) {
        return c-'a';
    }
public:
    void init() {
        s[1].init();
        p=0;
        ls=2;
    }
    void Insert(char ch[]) {
        int head=1;
        for(int k=0; ch[k]; k++) {
            int id=f(ch[k]);
            if(!s[head].next[id]) {
                s[head].next[id]=ls;
                s[ls++].init();
            }
            head=s[head].next[id];
            s[head].num++;
        }
        s[head].ptr=p++;
    }
    int query(char ch[],int op) {
        int head=1;
        for(int k=0; ch[k]&&head; k++) {
            head=s[head].next[f(ch[k])];
        }
        if(op) {
            if(head) return s[head].ptr;
            return -1;
        } else {
            if(head) return s[head].num;
            return 0;
        }
    }
} ts;

char str[123];
double ma[10];

int main() {
    int n,m;
    while(~scanf("%d%d",&n,&m)) {
        ts.init();
        for(int i=0; i<n; i++) {
            scanf("%s",&str);
            ts.Insert(str);
        }

        int ans = 0;
        while(m--) {
            int k;
            scanf("%d",&k);
            mt(str,0);
            int pre = 0;
            for(int i=0; i<k; i++) {
                double minma = inf;
                for(int j=0; j<8; j++) {
                    scanf("%lf",&ma[j]);
                    minma = min(minma,ma[j]);
                }
                int bin[10];
                for(int j=0; j<8; j++) {
                    if((ma[j] - minma)/minma<0.2) {
                        bin[j] = 0;
                    } else {
                        bin[j] = 1;
                    }
                }
                int val = 0;
                int mul = 1;
                for(int j=7;j>=0;j--){
                    val += mul * bin[j];
                    mul *= 2;
                }
                str[pre] = val;
                pre++;
            }
            ans += ts.query(str,0);
        }

        printf("%d\n",ans);

    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值