• [Usaco2008 Dec]Secret Message 秘密信息


    题意

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

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

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

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

    分析

    参照jklover的题解。

    将信息串插入 Trie 树中,记录子树大小.询问时,是密码串前缀的,在搜索过程中会经过,密码串是它的前缀的,到最后一个字符处加上子树大小即可.

    时间复杂度:线性。

    代码

    实现起来有个细节,根节点必须是1。因为如果按密码串匹配中途失败之后,就不应该继续匹配,而是一直停留在一个无效节点。所以把根节点设成1,然后无效节点自动为0,解决了这个技术问题。

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read()
    {
    	rg T data=0,w=1;
    	rg char ch=getchar();
    	while(!isdigit(ch))
    	{
    		if(ch=='-') w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch))
    	{
    		data=data*10+ch-'0';
    		ch=getchar();
    	}
    	return data*w;
    }
    template<class T>il T read(rg T&x)
    {
    	return x=read<T>();
    }
    typedef long long ll;
    using namespace std;
    co int N=5e5+1;
    int tot=1,ch[N][2],val[N],siz[N];
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	int n=read<int>(),m=read<int>();
    	while(n--)
    	{
    		int u=1,l=read<int>(); // edit 1:root must be 1
    		while(l--)
    		{
    			int b=read<int>();
    			if(!ch[u][b]) ch[u][b]=++tot;
    			u=ch[u][b],++siz[u];
    		}
    		++val[u],--siz[u];
    	}
    	while(m--)
    	{
    		int u=1,l=read<int>(),ans=0;
    		while(l--)
    		{
    			int b=read<int>();
    			u=ch[u][b];
    			ans+=val[u];
    		}
    		ans+=siz[u];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    iOS委托传值
    关于异步和多线程的关系
    删除xcode中的插件
    iOS Xcode常用插件
    关于ECSlidingViewController的使用
    iOS去掉tableview中无内容的cell
    iOS中block用法之两个界面传值问题
    cocoapods管理第三方类库
    在GitHub托管代码-终端命令
    vsCode快捷键
  • 原文地址:https://www.cnblogs.com/autoint/p/10331516.html
Copyright © 2020-2023  润新知