zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      洛谷传送门BZOJ传送门

    秘密消息Secret Message

    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

    HINT

     

    0 matches only 010: 1 match 1 matches 1, 100, and 110: 3 matches 01 matches only 010: 1 match 01001 matches 010: 1 match 11 matches 1 and 110: 2 matches


      分析:

      并不难的一道$Trie$树。

      题目中的前缀长度为信息串与密码串中较短的一个,那么我们可以这么做,在$Trie$树的每一个节点记录一个$value$,表示该节点由多少个单词使用过,在每一个信息串的末尾记录一个$id$,表示该单词共出现过几次。然后比较的时候统计经过的所有完整的单词数,然后如果扫完了整个密码串,我们需要判断一下当前扫到的位置是否是末端点,如果不是还需要把包含该节点但不在该节点处结尾的单词数统计一下。注意细节即可。(说的比较绕,看不懂就直接看代码吧)

      Code:

    //It is made by HolseLee on 12th Aug 2018
    //luogu.org P2922 
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=5e5+7;
    int n,m,tot,s[N];
    struct Node{
        int nx[2],val,id;
    }t[N];
    struct Trie{
        void ins()
        {
            int root=0;
            for(int i=1;i<=s[0];++i){
                if(!t[root].nx[s[i]]){
                    t[root].nx[s[i]]=++tot;
                    t[t[root].nx[s[i]]].val=0;
                }
                root=t[root].nx[s[i]];
                t[root].val++;
                if(i==s[0])t[root].id++;
            }
        }
    
        int quary()
        {
            int root=0,ret=0;bool flag=false;
            for(int i=1;i<=s[0];++i){
                root=t[root].nx[s[i]];
                if(!root){
                    flag=true;break;
                }
                ret+=t[root].id;
            }
            if(!flag)ret+=(t[root].val-t[root].id);
            return ret;
        }
    }T;
    
    inline int read()
    {
        char ch=getchar();int num=0;bool flag=false;
        while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
        while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
        return flag?-num:num;
    }
    
    int main()
    {
        n=read();m=read();
        t[0].val=0;
        for(int i=1;i<=n;++i){
            s[0]=read();
            for(int j=1;j<=s[0];++j)s[j]=read();
            T.ins();
        }
        for(int i=1;i<=m;++i){
            s[0]=read();
            for(int j=1;j<=s[0];++j)s[j]=read();
            printf("%d
    ",T.quary());
        }
        return 0;
    }
  • 相关阅读:
    C++学习基础十一——子类对象向父类对象的转化
    C++学习基础十——子类构造函数与析构函数的执行
    C++学习基础九——继承
    浅谈OpenGL变换矩阵
    笔记-Ajax[3]-ajax类终极版;
    笔记-Ajax[1]-的整体流程。
    笔记-[js兼容]-滚动条的滚动距离的兼容性问题解决方法。
    JS中的一些不常用的知识点。
    笔记-[面向对象]-JS基于面向对象编程-[2]
    笔记-[面向对象]-JS基于面向对象编程-[1]
  • 原文地址:https://www.cnblogs.com/cytus/p/9464455.html
Copyright © 2011-2022 走看看