[字典树,trie树] 树之呼吸-肆之型-前缀统计
2024-09-07 08:30:02
D.树之呼吸-肆之型-前缀统计 | |||||
|
|||||
Description | |||||
给定 n 个字符串 S1,S2,...,Sn。 接下来进行 m 次询问,每次询问给定一个字符串 T, 求 S1 ~ Sn 中有多少个字符串是 T 的前缀。 |
|||||
Input | |||||
输入第一行为一个正整数 case,表示测试数据组数; 对于每组测试数据,输入第一行为一个正整数 n,表示给定的字符串数; 接下来 n 行,给出 n 个字符串 S1 ~ Sn; 接下来一行一个正整数 m,表示询问数; 接下来 m 行,给出 m 个询问串 T1 ~ Tm; 保证: case <= 50; 给定串和询问串均只由大小写字母组成; 给定串和询问串的总长均不超过 2e5。 |
|||||
Output | |||||
对于每组测试数据,输出 m 行,每行一个整数,表示有多少个给定串是 T1 ~ Tm 的前缀。 | |||||
Sample Input | |||||
2 3 aab aa a 3 aa aab aabc 3 ABA ABA AAB 3 AB ABAab AAB |
|||||
Sample Output | |||||
2 3 3 0 2 1 |
|||||
Author | |||||
陈鑫 |
题意: 给定 n 个字符串 S1,S2,...,Sn.
接下来进行 m 次询问,每次询问给定一个字符串 T,
求 S1 ~ Sn 中有多少个字符串是 T 的前缀.
思路:给n个单词建一个字典树,在枚举Ti的前缀,看字典树中是否存在这个前缀,如果存在则答案加上这个单词出现的次数
注意:
这里正常来说按题意数组长度应该开2e5,但用memset会超时,正确做法是用fill并且去掉第一次初始化(把初始化放结尾),这里开1e5能过是因为数据水了,
注意字母有大小写A在a的前面,所以s[i]-'A',来得到字母的编号
ed[rt]标记不仅可以表示是否存在,也可以用来统计出现的次数
注意如果用了freopen则不能关闭流同步,也就是ios::sync_with_stdio(0),否则可以关闭流同步
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int amn=1e5+; ///这里正常来说应该开2e5,但用memset会超时,正确做法是用fill并且去掉第一次初始化(把初始化放结尾),这里开1e5能过是因为数据水了,
int tr[amn][],ed[amn],tot,x,ans,len,rt;
void init(){
memset(tr,,sizeof tr); ///在2e5的情况下的正确做法是用fill,不然用memset会超时
memset(ed,,sizeof ed);
tot=;
}
char s[amn];
void add(){
len=strlen(s),rt=;
for(int i=;i<len;i++){
x=s[i]-'A'; ///注意字母有大小写A在a的前面,所以s[i]-'A',来得到字母的编号
if(!tr[rt][x])tr[rt][x]=++tot;
rt=tr[rt][x];
}
ed[rt]++; ///这里由ed[rt]=1,变为了ed[rt]++,可以统计相同的单词出现了几次
}
void sol(){
len=strlen(s),rt=,ans=;
for(int i=;i<len;i++){
x=s[i]-'A';
if(!tr[rt][x])return; ///如果下面没结点就不用匹配了
rt=tr[rt][x];
if(ed[rt])ans+=ed[rt]; ///如果出现了一个单词,则答案加上单词出现的次数
}
}
int main(){
// freopen("in.txt","r",stdin);
// cin.sync_with_stdio(0);
///注意如果用了freopen则不能关闭流同步,也就是ios::sync_with_stdio(0),否则可以关闭流同步
int T,n,m;scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
while(n--){
cin>>s;
add();
}
scanf("%d",&m);
while(m--){
cin>>s;
sol();
printf("%d\n",ans);
}
}
}
/**
题意: 给定 n 个字符串 S1,S2,...,Sn.
接下来进行 m 次询问,每次询问给定一个字符串 T,
求 S1 ~ Sn 中有多少个字符串是 T 的前缀.
思路:给n个单词建一个字典树,在枚举Ti的前缀,看字典树中是否存在这个前缀,如果存在则答案加上这个单词出现的次数
注意:
这里正常来说按题意数组长度应该开2e5,但用memset会超时,正确做法是用fill并且去掉第一次初始化(把初始化放结尾),这里开1e5能过是因为数据水了,
注意字母有大小写A在a的前面,所以s[i]-'A',来得到字母的编号
ed[rt]标记不仅可以表示是否存在,也可以用来统计出现的次数
注意如果用了freopen则不能关闭流同步,也就是ios::sync_with_stdio(0),否则可以关闭流同步
**/
最新文章
- 如何理解vue.js组件的作用域是独立的
- Twitter的分布式自增ID算法snowflake (Java版)
- 算法:求幂(python版)
- ubuntu SVN环境配置(转)
- jboss jndi配置部分参数详解
- innodb_io_capacity >;=innodb_lru_scan_depth*inoodb_buffer_pool_instances。与 checkpoint
- C# typeof Gettype is as &;拆箱 装箱
- Linux 程序启停脚本
- hive j简单邮件过滤
- Scala学习之延迟绑定
- C# ASP.net 入门之简单通讯录
- [js高手之路]深入浅出webpack教程系列4-插件使用之html-webpack-plugin配置(上)
- JVM介绍&;自动内存管理机制
- p3966单词
- HDU-1698-Just a Hook-线段树区间修改
- 【XSY2680】玩具谜题 NTT 牛顿迭代
- Java Web之Web组件之间的跳转方式
- Java面试集合(三)
- 如何在Qt Creator中导入图标资源
- hdu 3289 最大独立集