2019.08.28 日常总结

光阴如梭,还有3天又要开学了。

一本通1576:

【题意】:

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

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

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

【思路】:先对截获的信息建一颗Trie字典树,同时维护以下几个值:

1、is_end[u]:表示是否有单词以编号为u的节点为结束符

2、b[u]:表示有多少个单词经过编号为u的节点

那么统计变得简单:在对密码进行遍历字典树时,如果is_end[u]==true,那么答案个数+1,最后返回答案个数+b[u]

#include 
using namespace std;
const int N=5e5+3e2;
int ch[N][2],tot,b[N];
int n,m,l,i,s[11000],j;
bool is_end[N];
inline void insert(int l){
	register int i,u=0;
	for(i=1;i<=l;i++){
		register int c=s[i];
		if (ch[u][c]==-1)
		ch[u][c]=++tot;
		u=ch[u][c];b[u]++;
	}
	is_end[u]++;
}
inline int query(int l){
	register int cnt=0,u=0;
	for(int i=1;i<=l;i++){
		register int c=s[i];
		if (ch[u][c]==-1)
		return cnt;
//		无法匹配,直接返回  
		u=ch[u][c];
		cnt+=is_end[u];
//		别人是它的前缀  
	}
	return cnt+b[u];//它是别人的前缀  
}
int main(){
	freopen("t1.in","r",stdin);
	memset(ch,-1,sizeof(ch));
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%d",&l);
		for(j=1;j<=l;j++)
		scanf("%d",&s[j]);
		insert(l);
	}
	for(i=1;i<=m;i++){
		scanf("%d",&l);
		for(j=1;j<=l;j++)
		scanf("%d",&s[j]);
		printf("%d\n",query(l));
	}
	return 0;
}

但是,我们发现以上代码连样例都过不了,为什么?

如图(用鼠标画的,有点丑),黑线表示边,黑色数字表示边上的字符,红色数字表示有多少个信息以该节点结尾,蓝色数字表示有多少个数字经过该节点,我们发现,当我们查询密码为“1”时,本来答案是3(“1”,“11”,“101”),但输出是4,为什么?因为在节点1处重复统计了!

怎么办?很简单,对于is_end[u]=true的节点u,b[u]--即可AC

//The AC code by hpwwzyy2012
#include 
using namespace std;
const int N=5e5+3e2;
int ch[N][2],tot,b[N];
int n,m,l,i,s[11000],j;
bool is_end[N];
inline void insert(int l){
	register int i,u=0;
	for(i=1;i<=l;i++){
		register int c=s[i];
		if (ch[u][c]==-1)
		ch[u][c]=++tot;
		u=ch[u][c];b[u]++;
	}
	is_end[u]++;b[u]--;
}
inline int query(int l){
	register int cnt=0,u=0;
	for(int i=1;i<=l;i++){
		register int c=s[i];
		if (ch[u][c]==-1)
		return cnt;
//		无法匹配,直接返回  
		u=ch[u][c];
		cnt+=is_end[u];
//		别人是它的前缀  
	}
	return cnt+b[u];//它是别人的前缀  
}
int main(){
	freopen("t1.in","r",stdin);
	memset(ch,-1,sizeof(ch));
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%d",&l);
		for(j=1;j<=l;j++)
		scanf("%d",&s[j]);
		insert(l);
	}
	for(i=1;i<=m;i++){
		scanf("%d",&l);
		for(j=1;j<=l;j++)
		scanf("%d",&s[j]);
		printf("%d\n",query(l));
	}
	return 0;
}
​

 

你可能感兴趣的:(原创)