牛客15334 Easygoing Single Tune Circulation(后缀自动机+字典树)
传送门:Easygoing Single Tune Circulation
题意
给定n个字符串 s[i],再给出m个查询的字符串 t[i],问 t[i] 是否为某个 s[i] 循环无限次的子串。
题解
分成两种情况
① t[i] 比 s[j] 短, 这个时候可以用后缀自动机,把每个 s[j] 重复一次,然后放到SAM中,这样直接每次直接查询就好了。当然,因为是有t(t<=1e5)组数据,全部初始化肯定会超时的,所以下一个要用到哪部分哪部分就初始化,这样最多初始化1e6次,因为所有的长度不会超过1e6。
② t[i] 比 s[j] 长,这样的话就不能用后缀自动机了,因为并不知道 t[i] 到底是 s[j] 重复了几次的子串。考虑到 t[i] 如果是某个 s[j] 循环无限次的子串,那么他一定是有循环节的,因为不知道有没有循环节,所以找到第一个最长的且每个字母只出现了一次的子串,并用最小表示法表示,然后在一颗插入了每个 s[j] 的最小表示法的字典树中查找是否有这个子串,如果有的话,构造长度为 |t[i]|,以该子串为循环节的串,如果这个串就是 t[i] 那么说明有该串,否则没有。当然,字典树的初始化也会卡,所以同样的边用边初始化下一个即将要用的。
代码
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 const int maxn=1e6+10;
5
6 struct SAM
7 {
8 int mxlen[maxn<<1],link[maxn<<1],nt[maxn<<1][26];
9 int sz,last,len;
10 void init()
11 {
12 memset(nt[0],0,sizeof(nt[0]));
13 mxlen[0]=0;
14 link[0]=-1;
15 sz=1;
16 last=0;
17 }
18
19 void extend(int c)
20 {
21 c-='a';
22 int cur=sz++;
23 mxlen[cur]=mxlen[last]+1;
24 int p=last;
25 memset(nt[cur],0,sizeof(nt[cur]));
26 while(p!=-1&&!nt[p][c]){
27 nt[p][c]=cur;
28 p=link[p];
29 }
30 if(p==-1) link[cur]=0;
31 else{
32 int q=nt[p][c];
33 if(mxlen[p]+1==mxlen[q]) link[cur]=q;
34 else{
35 int clone=sz++;
36 mxlen[clone]=mxlen[p]+1;
37 memcpy(nt[clone],nt[q],sizeof(nt[q]));
38 link[clone]=link[q];
39 while(p!=-1&&nt[p][c]==q){
40 nt[p][c]=clone;
41 p=link[p];
42 }
43 link[q]=link[cur]=clone;
44 }
45 }
46 last=cur;
47 }
48 bool query(string s)
49 {
50 int p=0;
51 for(int i=0;i<s.size();i++){
52 int c=s[i]-'a';
53 if(!nt[p][c]) return 0;
54 p=nt[p][c];
55 }
56 return 1;
57 }
58 }sam;
59
60 struct Trie
61 {
62 int tree[maxn][30];
63 int color[maxn];
64 int k=1;
65
66 int newnode()
67 {
68 memset(tree[k],0,sizeof(tree[k]));
69 color[k]=0;
70 return k++;
71 }
72
73 void init()
74 {
75 color[0]=0;
76 memset(tree[0],0,sizeof(tree[0]));
77 k=1;
78 }
79
80 void insert(string a)
81 {
82 int p=0;
83 int len=a.size();
84 for(int i=0;i<len;i++){
85 int c=a[i]-'a';
86 if(!tree[p][c]) {
87 tree[p][c]=newnode();
88 }
89 p=tree[p][c];
90 }
91 color[p]++;
92 }
93 int query(string a)
94 {
95 int p=0;
96 int len=a.size();
97 for(int i=0;i<len;i++){
98 int c=a[i]-'a';
99 if(!tree[p][c]) return 0;
100 p=tree[p][c];
101 }
102 return color[p];
103 }
104 }trie;
105
106 const int maxm=1e5+10;
107 string s[maxm];
108
109 string get_min(string s)
110 {
111 string t;
112 int p=26,pos=0;
113 for(int i=0;i<s.size();i++){
114 if(s[i]-'a'<=p) p=s[i]-'a',pos=i;
115 }
116 t=s.substr(pos);
117 t+=s.substr(0,pos);
118 return t;
119 }
120
121 int main()
122 {
123 ios::sync_with_stdio(false);
124 cin.tie(0);
125 cout.tie(0);
126 int T;
127 cin>>T;
128 int k=1;
129 while(T--){
130 sam.init();
131 trie.init();
132 cout<<"Case #"<<k++<<":"<<endl;
133 int n;
134 cin>>n;
135 for(int i=0;i<n;i++){
136 cin>>s[i];
137 string t=get_min(s[i]);
138 trie.insert(t);
139 }
140 for(int i=0;i<n;i++){
141 sam.last=0;
142 for(int j=0;j<s[i].size();j++) sam.extend(s[i][j]);
143 for(int j=0;j<s[i].size();j++) sam.extend(s[i][j]);
144 }
145 int m;
146 cin>>m;
147 while(m--){
148 string a;
149 cin>>a;
150 if(sam.query(a)){
151 cout<<"YES"<<endl;
152 continue;
153 }
154 int pos=a.size();
155 for(int i=1;i<pos;i++){
156 if(a[i]==a[0]){
157 pos=i;
158 break;
159 }
160 }
161 string t=a.substr(0,pos);
162 string tt=get_min(t);
163 if(trie.query(tt)){
164 string p;
165 for(int i=0;i<a.size();i++){
166 p+=t[i%t.size()];
167 }
168 if(p==a){
169 cout<<"YES"<<endl;
170 continue;
171 }
172 }
173 cout<<"NO"<<endl;
174 }
175 }
176 return 0;
177 }
牛客15334 Easygoing Single Tune Circulation(后缀自动机+字典树)的更多相关文章
- BZOJ3413: 匹配(后缀自动机 线段树合并)
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...
- cf666E. Forensic Examination(广义后缀自动机 线段树合并)
题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并 首先对所有的\(t_i\)建个广义后缀自动机,这样可以得到所有子串信息. 考虑把询问离线,然后把\(S\)拿到自动机上跑,同时维护一下 ...
- 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...
- BZOJ1396: 识别子串(后缀自动机 线段树)
题意 题目链接 Sol 后缀自动机+线段树 还是考虑通过每个前缀的后缀更新答案,首先出现次数只有一次,说明只有\(right\)集合大小为\(1\)的状态能对答案产生影响 设其结束位置为\(t\),代 ...
- [Luogu5161]WD与数列(后缀数组/后缀自动机+线段树合并)
https://blog.csdn.net/WAautomaton/article/details/85057257 解法一:后缀数组 显然将原数组差分后答案就是所有不相交不相邻重复子串个数+n*(n ...
- 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)
题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...
- luogu5212/bzoj2555 substring(后缀自动机+动态树)
对字符串构建一个后缀自动机. 每次查询的就是在转移边上得到节点的parent树中后缀节点数量. 由于强制在线,可以用动态树维护后缀自动机parent树的子树和. 注意一个玄学的优化:每次在执行连边操作 ...
- 模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合)
模板—字符串—后缀自动机(后缀自动机+线段树合并求right集合) Code: #include <bits/stdc++.h> using namespace std; #define ...
- 【BZOJ4556】[TJOI2016&HEOI2016] 字符串(后缀自动机+线段树合并+二分)
点此看题面 大致题意: 给你一个字符串\(s\),每次问你一个子串\(s[a..b]\)的所有子串和\(s[c..d]\)的最长公共前缀. 二分 首先我们可以发现一个简单性质,即要求最长公共前缀,则我 ...
随机推荐
- MySQL45讲:一条update语句是怎样执行的
首先创建一张表: create table T(ID int primary key,c int); 如果要更新ID=2这行+1:应该这样写 update T set c=c+1 where ID=2 ...
- 天梯赛练习 L3-007 天梯地图 (30分) Dijkstra
题目分析: 本题的题意比较清晰,就是有一个起点和一个终点,给出m条路径,可能是单向的可能是双向的,同时一条路有两个权重,分别是通过这条路需要的时间和这条路的路径长度,题目需要求出两条路径,一条是在最快 ...
- RecyclerView 源码分析(一) —— 绘制流程解析
概述 对于 RecyclerView 是那么熟悉又那么陌生.熟悉是因为作为一名 Android 开发者,RecyclerView 是经常会在项目里面用到的,陌生是因为只是知道怎么用,但是却不知道 Re ...
- ps ww
[root@ma ~]# ps ww -p 1 PID TTY STAT TIME COMMAND 1 ? Ss 0:01 /sbin/init[root@ma ~]# ps -p 1 PID TTY ...
- 【Git】3、创建Git版本库、配置Git仓库用户邮箱信息
初识Git 文章目录 初识Git 1.创建Git版本库 认识.git 2.基础配置 2.1.查看配置信息 2.2.配置昵称邮箱信息 2.3.修改配置信息 1.通过命令行 2.通过修改配置文件. 修改全 ...
- 【Linux】md5sum 生产所有文件的md5值,并对照目标文件是否相同
现在加入有很多很多文件需要测试md5,想看下是否都传输成功了,如何批量生成文件的md5并且逐条对照呢? 下面来简单介绍下 md5sum这个命令有一个选项"-c" 这个选项的意思是c ...
- 使用yaml配置文件管理资源
[root@k8s-master ~]# vim nginx-deployment.yaml apiVersion: apps/v1beta2 kind: Deployment metadata: n ...
- mysql:如何解决数据修改冲突(事务+行级锁的实际运用)
摘要:最近做一个接诊需求遇到一个问题,假设一个订单咨询超过3次就不能再接诊,但如果两个医生同时对该订单进行咨询,查数据库的时候查到的接诊次数都是2次,那两个医生都能接诊,所谓接诊可以理解为更新了接诊次 ...
- 接收的参数为日期类型、controller控制层进行数据保存、进行重定向跳转
目录 1.接收的参数为日期类型 2.controller控制层进行数据保存 3.controller层如何进行重定向跳转(因为默认是请求转发) 4.静态资源的映射 1.接收的参数为日期类型 WEB-I ...
- Java运算符及包机制
Java中的运算符及包机制 算术运算符:+ - * / % ++ -- 赋值运算符:=,+=,-=,*=,/= 关系运算符:>,<,>=,<=,==,!=,instanceof ...