题目大意:给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#include #include #include #include #include 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;}