Bzoj1590——Secret Message(Trie)

本文介绍了一道USACO编程竞赛题目的解决方案,题目要求计算被截获的二进制信息与密码间的匹配数量。通过构建Trie树结构,有效解决了信息匹配问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem 1590. – [Usaco2008 Dec]Secret Message 秘密信息

1590: [Usaco2008 Dec]Secret Message 秘密信息

Time Limit: 5 Sec   Memory Limit: 32 MB
Submit: 420   Solved: 278
[ Submit][ Status][ Discuss]

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

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

这道题一开始题目看错,搞得我纠结了45min多o(╥﹏╥)o其实很简单啦

题解

用秘密信息来建一颗Trie树:
对于每个密码我们可以知道在Trie树上它能覆盖多少条信息或者被多少条信息覆盖,需要维护这两个量
然后需要记录每个结点是多少个字符串的尾结点,同时把每次路径上所有点的覆盖标记加1。
查询的时候就可以把路径上所有尾结点标记之和加起来然后再把最后访问到的节点的覆盖值加上就可以了

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,t,x,ch[1000005][5],tot=1,c[1000005],bo[1000005],f[1000005],ans;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++){
        scanf("%d",&t);
        int u=1;
        for(int j=1; j<=t; j++){
            scanf("%d",&x);
            if(!ch[u][x]) ch[u][x]=++tot;
            u=ch[u][x];
            c[u]++;
        }
        bo[u]++;
    }
    for(int i=1; i<=m; i++){
        scanf("%d",&t);
        for(int i=1; i<=t; i++) scanf("%d",&f[i]);
        int u=1,ans=0;
        bool flag=false;
        for(int i=1; i<=t; i++){
            if(!ch[u][f[i]]){
                flag=true;
                break;
            }
            u=ch[u][f[i]];
            ans+=bo[u];
        }
        if(!flag) ans+=c[u]-bo[u];
        printf("%d\n",ans);
    }
}

miao~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值