zoukankan      html  css  js  c++  java
  • 洛谷:P2922 [USACO08DEC]秘密消息(Trie树)

    P2922 [USACO08DEC]秘密消息Secret Message

    题目链接:https://www.luogu.org/problemnew/show/P2922

    题目描述

    贝茜正在领导奶牛们逃跑.为了联络,奶牛们互相发送秘密信息.

    信息是二进制的,共有M(1≤M≤50000)条.反间谍能力很强的约翰已经部分拦截了这些信息,知道了第i条二进制信息的前bi(l《bi≤10000)位.他同时知道,奶牛使用N(1≤N≤50000)条密码.但是,他仅仅了解第J条密码的前cj(1≤cj≤10000)位.

    对于每条密码J,他想知道有多少截得的信息能够和它匹配.也就是说,有多少信息和这条密码有着相同的前缀.当然,这个前缀长度必须等于密码和那条信息长度的较小者.

    在输入文件中,位的总数(即∑Bi+∑Ci)不会超过500000.

    输入输出格式

    输入格式:

    * Line 1: Two integers: M and N

    * Lines 2..M+1: Line i+1 describes intercepted code i with an integer b_i followed by b_i space-separated 0's and 1's

    * Lines M+2..M+N+1: Line M+j+1 describes codeword j with an integer c_j followed by c_j space-separated 0's and 1's

    输出格式:

    * Lines 1..M: Line j: The number of messages that the jth codeword could match.

    输入输出样例

    输入样例#1:
    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 
    
    输出样例#1:
    1 
    3 
    1 
    1 
    2 

    题解:

    直接在Trie上面匹配就行,Trie树上面记录一下以当前结点为结尾的点有多少以及有多少经过这个点就行了。

    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 500005;
    int n,m,cnt,tot;
    int s[N],val[N];
    struct Trie{
        int node,son,left,sum;
    }tre[N];
    void init(){
        tre[0].son=tre[0].left=-1;tot=1;
    }
    void insert(){
        int j,u=0;
        for(int i=0;i<cnt;i++){
            bool flag=false;
            for(j=tre[u].son;j!=-1;j=tre[j].left){
                if(tre[j].node==s[i]){
                    flag=true;
                    break ;
                }
            }
            if(!flag){
                j=tot++;
                tre[j].left=tre[u].son;
                tre[u].son=j;
                tre[j].node=s[i];
                tre[j].son=-1;
            }
            tre[j].sum++;
            u=j;
        }
        val[u]++;
    }
    int query(){
        int ans = 0;
        int u=0,j;
        for(int i=0;i<cnt;i++){
            bool flag=false;
            for(j=tre[u].son;j!=-1;j=tre[j].left){
                if(tre[j].node==s[i]){
                    flag=true;
                    break ;
                }
            }
            if(!flag) break ;
            if(i==cnt-1){
                ans+=tre[j].sum;
                break ;
            }
            ans+=val[j];
            u=j;
        }
        return ans ;
    }
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
        cin>>m>>n;
        init();
        for(int i=1;i<=m;i++){
            int k,p;cnt=0;
            cin>>k;
            for(int j=1;j<=k;j++){
                cin>>p;
                s[cnt++]=p;
            }
            insert();
        }
        int ans = 0;
        for(int i=1;i<=n;i++){
            ans=cnt=0;int k,p;
            cin>>k;
            for(int j=1;j<=k;j++){
                cin>>p;
                s[cnt++]=p;
            }
            ans+=query();
            cout<<ans<<'
    ';
        }
        return 0;
    }
  • 相关阅读:
    多测师讲解html _伪类选择器17_高级讲师肖sir
    多测师讲解html _后代选择器16_高级讲师肖sir
    多测师讲解html _组合选择器_高级讲师肖sir
    多测师讲解html _标签选择器14_高级讲师肖sir
    前端 HTML form表单标签 input标签 type属性 重置按钮 reset
    前端 HTML form表单标签 textarea标签 多行文本
    前端 HTML form表单标签 input标签 type属性 file 上传文件
    前端 HTML form表单标签 input标签 type属性 radio 单选框
    前端 HTML form表单标签 input标签 type属性 checkbox 多选框
    前端 HTML form表单目录
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10468738.html
Copyright © 2011-2022 走看看