题目大意:给n个字符串,给m个询问,每个询问给k个条形码。每个条形码由8个小码组成,每个小码有相应的宽度,已知一个条形码的宽度只有2种,宽的表示1,窄的表示0。并且宽的宽度是窄的宽度的2倍。由于扫描的时候有误差,每个小码的宽度为一个浮点型数据,保证每个数据的误差在5%内。所以一个条形码可以对应一个ASCC码,表示一个小写字母。k个条形码表示一个字符串s,每个询问表示给定的m个字符串中以s为前缀的字符串个数。
题目分析:将n个字符串插入到字典树中,并记录下每个前缀有多少个字符串。即每插入一个字符串,在相应路径上+1,然后就是模拟出字符串s,在字典树中查询即可。
关于条形码数据的处理:输入的时候记录下8个数据中的最大值,然后对于所有的数据,满足fabs(mx - data[i])/mx < 0.1的,那么第i为为1,否则0。
详情请见代码:
- #include <iostream>
- #include<cstdio>
- #include<cstring>
- #include<cmath>
- #include<algorithm>
- #include<string>
- using namespace std;
- const int N = 10005;
- const int M = 2005;
- const int NM = 10000005;
- const double eps = 1e-6;
- typedef __int64 ll;
- struct node
- {
- int cnt;
- int next[26];
- }trie[NM];
- int num,n,m;
- double dt[9];
- char str[M];
- void init(int x)
- {
- memset(trie[x].next,0,sizeof(trie[x].next));
- trie[x].cnt = 0;
- }
- void insert(int cur,int dp,int len)
- {
- trie[cur].cnt ++;
- if(dp == len)
- return;
- if(trie[cur].next[str[dp] - 'a'] == 0)
- {
- trie[cur].next[str[dp] - 'a'] = num;
- init(num);
- num ++;
- }
- insert(trie[cur].next[str[dp] - 'a'],dp + 1,len);
- }
- int query(int cur,int dp,int len)
- {
- if(dp == len)
- return trie[cur].cnt;
- if(trie[cur].next[str[dp] - 'a'])
- return query(trie[cur].next[str[dp] - 'a'],dp + 1,len);
- else
- return 0;
- }
- int main()
- {
- int i,j,k;
- while(scanf("%d%d",&n,&m) != EOF)
- {
- num = 1;
- ll ans = 0;
- init(0);
- while(n --)
- {
- scanf("%s",str);
- int len = strlen(str);
- insert(0,0,len);
- }
- while(m --)
- {
- scanf("%d",&k);
- for(i = 0;i < k ;i ++)
- {
- double mx = 0;
- int code = 0;
- for(j = 0;j < 8;j ++)
- {
- scanf("%lf",&dt[j]);
- if(dt[j] - mx > eps)
- mx = dt[j];
- }
- for(j = 0;j < 8;j ++)
- {
- if(fabs(mx - dt[j])/mx - 0.1 < eps)
- code += (1<<(7 - j));
- }
- str[i] = code;
- }
- str[k] = '\0';
- ans += query(0,0,k);
- }
- printf("%I64d\n",ans);
- }
- return 0;
- }