Trie字典树和AC自动机(题目)

2024-06-06 06:12
文章标签 题目 字典 ac trie 自动机

本文主要是介绍Trie字典树和AC自动机(题目),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

A. 三年二班的投票

题目描述:

三年级二班已经完成了竞选班长的投票,已知一共有 n 张投票,每张投票上写了一位同学的名字。

投票统计结束后,张老师随意问一个同学的名字,请编程快速检索出,该同学共有几票。

输入:

第一行读入一个整数 n ,代表产生了 n 张投票。( n≤10^5 )

接下来 n 行,每行有一个字符串 s ,代表该张投票上写的同学的姓名(姓名由不含空格的小写英文字母组成,n 个姓名的总长度 ≤10^6 。

接下来一行读入一个整数 m( m≤10^5 ),代表王老师提问的同学的姓名数量。

接下来 m 行,每行有一个字符串 t ,代表每次询问的姓名;(姓名由不含空格的小写英文字母组成,m 个姓名的总长度 ≤10^6 )。

输出:

输出 m 行,第 i 行输出第 i 次询问的姓名,在投票中出现的总次数。

样例:

输入:

5
lihua
zhaoxiang
wangfang
lihua
zhangxiang
3
lihua
wangfang
sunming

输出:

2
1
0

代码如下:

#include <bits/stdc++.h>
using namespace std;const int N = 1e6 + 10;
//下标为0的行,表示根,也表示空节点 
int ch[N][26];//字典树
//cnt:以第i个字母结尾的单词有多少个 
int cnt[N],idx; 
char s[N];//每次读入的名字
int n,m;//建字典树
void insert(char s[]){int p = 0;//从下标为0的行开始for(int i = 0;s[i];i++){int u = s[i] - 'a';//转换为0~25//如果p节点不存在u这个子结点,则创建子结点 if(!ch[p][u]) ch[p][u] = ++idx;p = ch[p][u];} cnt[p]++;//结束,以第p个字母结尾的字符串数量+1 
} //查询:返回字符串出现的次数
int query(char s[]){int p = 0;for(int i = 0;s[i];i++){int u = s[i] - 'a';if(!ch[p][u]) return 0;//没有出现p = ch[p][u]; }return cnt[p];
}int main(){scanf("%d",&n);while(n--){scanf("%s",s);insert(s);}scanf("%d",&m);while(m--){scanf("%s",s);printf("%d\n",query(s));}return 0;
}

B. 数字串前缀匹配

题目描述:

给定 n 个长度不超过 10 的数字串,问其中是否存在两个数字串 S,T,使得 S 是 T 的前缀。

本题读入多组数据,请对每组数据进行计算并输出结果。(数据组数≤40,n≤10^4)

输入:

第一行一个整数 T,表示数据组数。

对于每组数据,第一行一个数 n,接下来 n 行输入 n 个数字串。

输出:

对于每组数据,若存在两个数字串 S,T,使得 S 是 T 的前缀,则输出 NO ,否则输出 YES 。

样例:

输入:

2
3
911
97625999
91125426
5
113
12340
123440
12345
98346

输出:

NO
YES

 代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int ch[N][10];
int cnt[N];
char s[20];
int n,T,idx;
bool insert(char s[]){bool f1=0;bool f2=0;int p=0;for(int i=0;s[i];i++){int x=s[i]-'0';if(!ch[p][x]) ch[p][x]=++idx,f1=1;p=ch[p][x];if(cnt[p]!=0) f2=1;}cnt[p]++;return (f1==0)||f2;
}
int query(char s[]){int p=0;for(int i=0;s[i];i++){int x=s[i]-'a';if(!ch[p][x]) return 0;p=ch[p][x];}return cnt[p];
}
int main(){scanf("%d",&T);while(T--){memset(ch,0,sizeof(ch));memset(cnt,0,sizeof(cnt));idx=0;scanf("%d",&n);bool f=0;while(n--){scanf("%s",s);if(insert(s)) f=1;}if(f) printf("NO\n");else printf("YES\n");}return 0;
}

C. 关键词搜索

题目描述:

给定 n 个长度不超过 50 的由小写英文字母组成的单词准备查询,以及一篇长为 m 的文章,问:文中出现了多少个待查询的单词。多组数据。

输入:

第一行一个整数 T,表示数据组数;
对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串(不含空格),表示文章。(对于全部数据,1≤n≤104,1≤m≤106 。)

输出:

对于每组数据,输出一个数,表示文中出现了多少个待查询的单词(注意:同一个单词在文章中出现多次,也只算一次)。

样例:

输入:

1
5
she
he
say
shr
her
yasherhs

输出:

3

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=1e6+10,L=55;
int ch[N*L][26];
int cnt[N*L],ne[N*L],q[N*L];
char w[L],s[M];
int n,T,idx;
void init(){memset(ch,0,sizeof(ch));memset(cnt,0,sizeof(cnt));idx=0;memset(ne,0,sizeof(ne));
}
void bfs(){int h=1,t=0;for(int i=0;i<26;i++){if(ch[0][i]) q[++t]=ch[0][i];}while(h<=t){int f=q[h];for(int i=0;i<26;i++){if(ch[f][i]){int c=ch[f][i];int j=ne[f];while(j&&!ch[j][i]){j=ne[j];}if(ch[j][i]) j=ch[j][i];ne[c]=j;q[++t]=c;}}h++;}
}
void insert(char w[]){int p=0;for(int i=0;w[i];i++){int x=w[i]-'a';if(!ch[p][x]) ch[p][x]=++idx;p=ch[p][x];}cnt[p]++;
}
int main(){scanf("%d",&T);while(T--){init();scanf("%d",&n);while(n--){scanf("%s",w);insert(w);}bfs();scanf("%s",s);int res=0;for(int i=0,j=0;s[i];i++){int x=s[i]-'a';while(j&&!ch[j][x]) j=ne[j];if(ch[j][x]) j=ch[j][x];int p=j;while(p!=0){res+=cnt[p];cnt[p]=0;p=ne[p];}}printf("%d\n",res);}return 0;
}

这篇关于Trie字典树和AC自动机(题目)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035302

相关文章

hdu 3065 AC自动机 匹配串编号以及出现次数

题意: 仍旧是天朝语题。 Input 第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。 接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。 在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。

POJ 1625 自动机

给出包含n个可见字符的字符集,以下所提字符串均由该字符集中的字符构成。给出p个长度不超过10的字符串,求长为m且不包含上述p个字符串的字符串有多少个。 g++提交 int mat[108][108] ;int matn ;int N ;map<char ,int> to ;//ACconst int maxm = 108 ;const int kin

zoj 3228 ac自动机

给出一个字符串和若干个单词,问这些单词在字符串里面出现了多少次。单词前面为0表示这个单词可重叠出现,1为不可重叠出现。 Sample Input ab 2 0 ab 1 ab abababac 2 0 aba 1 aba abcdefghijklmnopqrstuvwxyz 3 0 abc 1 def 1 jmn Sample Output Case 1 1 1 Case 2

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

题目1380:lucky number

题目1380:lucky number 时间限制:3 秒 内存限制:3 兆 特殊判题:否 提交:2839 解决:300 题目描述: 每个人有自己的lucky number,小A也一样。不过他的lucky number定义不一样。他认为一个序列中某些数出现的次数为n的话,都是他的lucky number。但是,现在这个序列很大,他无法快速找到所有lucky number。既然

D4代码AC集

贪心问题解决的步骤: (局部贪心能导致全局贪心)    1.确定贪心策略    2.验证贪心策略是否正确 排队接水 #include<bits/stdc++.h>using namespace std;int main(){int w,n,a[32000];cin>>w>>n;for(int i=1;i<=n;i++){cin>>a[i];}sort(a+1,a+n+1);int i=1

POJ2001字典树

给出n个单词,求出每个单词的非公共前缀,如果没有,则输出自己。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.io.UnsupportedEncodingException;

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que

2024 年高教社杯全国大学生数学建模竞赛题目——2024 年高教社杯全国大学生数学建模竞赛题目的求解

2024 年高教社杯全国大学生数学建模竞赛题目 (请先阅读“ 全国大学生数学建模竞赛论文格式规范 ”) 2024 年高教社杯全国大学生数学建模竞赛题目 随着城市化进程的加快、机动车的快速普及, 以及人们活动范围的不断扩大,城市道 路交通拥堵问题日渐严重,即使在一些非中心城市,道路交通拥堵问题也成为影响地方经 济发展和百姓幸福感的一个“痛点”,是相关部门的棘手难题之一。 考虑一个拥有知名景区