BZOJ 1590: [Usaco2008 Dec]Secret Message 秘密信息
Time Limit: 5 Sec
Memory Limit: 32 MB
Submit: 277
Solved: 191
[Submit][Status][Discuss]
题解:
用秘密信息来建一颗Trie树:
对于每个密码我们可以知道在Trie树上它能覆盖多少条信息或者被多少条信息覆盖,需要维护这两个量
然后需要记录每个结点是多少个字符串的尾结点,同时把每次路径上所有点的覆盖标记加1。
查询的时候就可以把路径上所有尾结点标记之和加起来然后再把最后访问到的节点的覆盖值加上就可以了
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=500005;
int n,m,o,x,mp[N][2],cnt,cover[N],sp[N],f[N],ans;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&o);
int now=0;
for(int j=1;j<=o;j++)
{
scanf("%d",&x);
if(!mp[now][x]) mp[now][x]=++cnt;
now=mp[now][x];
cover[now]++;
}
sp[now]++;
}
for(int i=1;i<=m;i++)
{
scanf("%d",&o);
for(int i=1;i<=o;i++) scanf("%d",&f[i]);
int now=0,ans=0;
bool flag=false;
for(int i=1;i<=o;i++)
{
if(!mp[now][f[i]])
{
flag=true;
break;
}
now=mp[now][f[i]];
ans+=sp[now];
}
if(!flag) ans+=cover[now]-sp[now];
printf("%d\n",ans);
}
}
Description
贝茜正在领导奶牛们逃跑.为了联络,奶牛们互相发送秘密信息.
信息是二进制的,共有M(1≤M≤50000)条.反间谍能力很强的约翰已经部分拦截了这些信息,知道了第i条二进制信息的前bi(l《bi≤10000)位.他同时知道,奶牛使用N(1≤N≤50000)条密码.但是,他仅仅了解第J条密码的前cj(1≤cj≤10000)位.
对于每条密码J,他想知道有多少截得的信息能够和它匹配.也就是说,有多少信息和这条密码有着相同的前缀.当然,这个前缀长度必须等于密码和那条信息长度的较小者.
在输入文件中,位的总数(即∑Bi+∑Ci)不会超过500000.
Input
第1行输入N和M,之后N行描述秘密信息,之后M行描述密码.每行先输入一个整数表示信息或密码的长度,之后输入这个信息或密码.所有数字之间都用空格隔开.
Output
共M行,输出每条密码的匹配信息数.
Sample Input
4 5
3 0 1 0
1 1
3 1 0 0
3 1 1 0
1 0
1 1
2 0 1
5 0 1 0 0 1
2 1 1
INPUT DETAILS:
Four messages; five codewords.
The intercepted messages start with 010, 1, 100, and 110.
The possible codewords start with 0, 1, 01, 01001, and 11.
Sample Output
1
3
1
1
2