zoukankan      html  css  js  c++  java
  • 洛谷p2922[USACO08DEC]秘密消息Secret Message

    题目:###


    题目链接:[USACO08DEC]秘密消息Secret Message

    题意:##

    给定n条01信息和m条01密码,对于每一条密码A,求所有信息中包含它的信息条数和被它包含的信息条数的和。

    分析:##

    建立一棵trie树,类似于存储26个字母一样存储0和1(每个节点只有两个儿子),然后设包含节点p的信息条数有size[p]条,在节点p结束的信息条数有end[p]条,节点的两个儿子的编号为num[p][0]和num[p][1],然后存储信息。
    我们容易知道size[p]存储的实际上是包含了“从根节点走到p节点所代表的这条字符串”的所有字符串的总数(包括这条字符串自己)
    对于每一条读入的密码,我们把它存储在一个临时数组里,然后在这棵trie树上往下找,记录一个ans,走过每一个节点的时候ans+=end[p]。
    走的时候会有两种情况:

    • 这条路比这个密码短(即所有符合条件的信息都是这条密码的子集),那么走到尽头就可以了
    • 这条路比这个密码长,那么走到这条密码的尽头(这条密码的最后一个字符对应的节点)的时候ans+=size[p](见上面的解释),其余时间ans+=end[p]就可以了

    代码不长,我用结构体写的trie树(和上面分析的变量名字是一样的),然后不知道哪里的玄学优化(register?)起了作用好像跑得还有点快(…)
    里面的注释自认为比较齐全了


    代码:###

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int cnt=0,f=1;char c;
    	c=getchar();
    	while(!isdigit(c)){
    		if(c=='-')f=-f;
    		c=getchar();
    	}
    	while(isdigit(c)){
    		cnt=cnt*10+c-'0';
    		c=getchar();
    	}
    	return cnt*f;
    }
    int n,m,len,tot;//tot:记录节点编号 
    struct node{
    	int end;//记录有多少条信息在这个节点完结 
    	int size;//记录有多少条信息过这个节点 
    	int num[2];//记录左右儿子编号 
    }trie[500005];
    int a[50005];//临时数组,用于存放每次添加的信息或密码 
    inline void insert(int k){
    	int p=0;
    	for(register int i=1;i<=k;p=trie[p].num[a[i]],i++){
    		if(!trie[p].num[a[i]])trie[p].num[a[i]]=++tot;
    		trie[p].size++;
    	}
    	trie[p].size++;
    	trie[p].end++; 
    }
    inline int ask(int k){
    	int p=0;
    	int ans=0;
    	for(register int i=1;i<=k;p=trie[p].num[a[i]],i++){
    		int to=trie[p].num[a[i]];
    		if(!to)break;//如果这条路上没有更长的信息(走不动了)就不搜了 
    		if(i==k)ans+=trie[to].size;//如果这条密码走到头了就把包含它的串的个数都加上(这里包含了和它一样的串) 
    		else
    		ans+=trie[to].end;//如果没有走到头就把到这个节点完结的串的个数加上 
    	}
    	return ans;
    }
    int main(){
    	m=read();n=read();
    	for(register int i=1;i<=m;i++){
    		len=read();
    		for(register int j=1;j<=len;j++)a[j]=read();
    		insert(len);
    	}
    	for(register int i=1;i<=n;i++){
    		len=read();
    		for(register int j=1;j<=len;j++)a[j]=read();
    		printf("%d
    ",ask(len));
    	}
    	return 0;
    }
    
  • 相关阅读:
    jquery点滴总结
    优雅降级和渐进增强的区别
    editplus 常用
    whm 设置共享IP
    php抓取页面的几种方法详解
    上传数据插件 Easy Populate 遇到问题 ?langer=remove
    zencart里常用 SQL
    5个简单的步骤把 WordPress 打造成 CMS
    基于PHP的cURL快速入门
    常用软件、插件名称
  • 原文地址:https://www.cnblogs.com/kma093/p/9880498.html
Copyright © 2011-2022 走看看