HDU #5507 GT and Strings
这是AC自动机系列的第一篇
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)0
大意
给出N个仅由小写字母组成的字符串S[1]...S[N],它们的总长度为L。有Q组询问,询问分两类:
1.S[x]是否是S[y]的子序列;
2.S[x]是否是S[y]的子串。
数据范围:
N,L,Q<=100000,有60%的数据满足 L<=100, Q<=1000
Solution
void input(int n){
for(int i=; i<n; i++){
scanf("%s", s+beg[i]);
beg[i+]=beg[i]+strlen(s+beg[i]);
}
}
int nt[N][];
void calc_nt(int n){
memset(nt, -, *beg[n]<<);
for(int i=, j; i<n; i++){
j=beg[i+]-;
nt[j][s[j]-'a']=j;
for(j--; j>=beg[i]; j--)
for(int k=; k<; k++)
if(k==s[j]-'a') nt[j][k]=j;
else nt[j][k]=nt[j+][k];
}
}
查询时只要在串S[j]对应的nt表中不断往后匹配就可以了:
int subseq(int x, int y){
if(len(x)>len(y)) return ;
for(int i=beg[x], j=beg[y]; i<beg[x+]; i++){
if(j>=beg[y+]) return ;
if(nt[j][s[i]-'a']==-) return ;
j=nt[j][s[i]-'a']+;
}
return ;
}
判断子串的询问可用AC自动机离线处理。
AC代码
#include <bits/stdc++.h>
using namespace std; const int N(1e5+);
int beg[N], id[N];
char s[N]; void input(int n){
for(int i=; i<n; i++){
scanf("%s", s+beg[i]);
beg[i+]=beg[i]+strlen(s+beg[i]);
}
} int x[N], y[N];
void preprocess(int q, map<pair<int,int>,int> &mp){
mp.clear();
for(int i=; i<q; i++){
scanf("%d%d", x+i, y+i), x[i]--, y[i]--;
mp[{id[x[i]], id[y[i]]}];
}
} int nt[N][];
void calc_nt(int n){
memset(nt, -, *beg[n]<<);
for(int i=, j; i<n; i++){
j=beg[i+]-;
nt[j][s[j]-'a']=j;
for(j--; j>=beg[i]; j--)
for(int k=; k<; k++)
if(k==s[j]-'a') nt[j][k]=j;
else nt[j][k]=nt[j+][k];
}
} int len(int x){return beg[x+]-beg[x];} int subseq(int x, int y){
if(len(x)>len(y)) return ;
for(int i=beg[x], j=beg[y]; i<beg[x+]; i++){
if(j>=beg[y+]) return ;
if(nt[j][s[i]-'a']==-) return ;
j=nt[j][s[i]-'a']+;
}
return ;
} void solve1(int q, map<pair<int,int>,int> &mp, int *ans){
mp.clear();
for(int i=; i<q; i++){
if(mp.find({x[i], y[i]})==mp.end())
mp[{x[i], y[i]}]=subseq(x[i], y[i]);
ans[i]=mp[{x[i], y[i]}];
}
} int ch[N][], f[N], last[N], val[N];
void init(int i){
memset(ch[i], , sizeof(ch[i]));
f[i]=last[i]=val[i]=;
} void build_trie(int n){
int tot=; init(tot++);
for(int i=, ID=, u; i<n; i++){
for(int j=(u=,beg[i]); j<beg[i+]; j++){
int &v=ch[u][s[j]-'a'];
if(!v) v=tot++, init(v);
u=v;
}
if(!val[u]) val[u]=++ID;
id[i]=val[u];
}
} int que[N];
int build_ac(){
int head=, tail=;
for(int i=; i<; i++){
if(ch[][i]) que[tail++]=ch[][i];
}
for(int u; head!=tail;){
u=que[head++];
for(int i=; i<; i++){
int &v=ch[u][i];
if(v){
f[v]=ch[f[u]][i];
last[v] = val[f[v]] ? f[v] : last[f[v]];
que[tail++]=v;
}
else v=ch[f[u]][i];
}
}
} void solve2(int n, int q, map<pair<int,int>,int> &mp, int *ans){
for(int i=, x, y; i<n; i++){
y=id[i];
for(int j=beg[i], k=; j<beg[i+]; j++){
k=ch[k][s[j]-'a'];
x=val[k];
if(x&& mp.find({x, y})!=mp.end())
mp[{x,y}]=;
for(int l=last[k]; l; l=last[l]){
x=val[l];
if(mp.find({x, y})!=mp.end())
mp[{x,y}]=;
}
}
}
for(int i=; i<q; i++)
ans[i]=mp[{id[x[i]],id[y[i]]}];
}
int ans[][N];
map<pair<int,int>,int> mp[];
int main(){
int T; scanf("%d", &T);
for(int n, q; T--; puts("")){
scanf("%d%d", &n, &q);
input(n);
calc_nt(n);
build_trie(n);
build_ac();
preprocess(q, mp[]);
solve1(q, mp[], ans[]);
solve2(n, q, mp[], ans[]);
for(int i=; i<q; i++) printf("%d%d", ans[][i], ans[][i]);
}
}
HDU #5507 GT and Strings的更多相关文章
- HDU 5229 ZCC loves strings 博弈
题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5229 bc:http://bestcoder.hdu.edu.cn/contests/con ...
- 矩阵十题【五】 VOJ1049 HDU 2371 Decode the Strings
题目链接:https://vijos.org/p/1049 题目大意:顺次给出m个置换,重复使用这m个置换对初始序列进行操作.问k次置换后的序列.m<=10, k<2^31. 首先将这m个 ...
- hdu 1501 Zipper dfs
题目链接: HDU - 1501 Given three strings, you are to determine whether the third string can be formed by ...
- hdu 6208 The Dominator of Strings【AC自动机】
hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...
- HDU 6208 The Dominator of Strings(AC自动机)
The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java ...
- HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9
/* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问 ...
- 2017多校第9场 HDU 6170 Two strings DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6170 题意:给了2个字符串,其中第2个字符串包含.和*两种特别字符,问第二个字符串能否和第一个匹配. ...
- HDU 6170----Two strings(DP)
题目链接 Problem Description Giving two strings and you should judge if they are matched.The first strin ...
- hdu 6170 Two strings dp
Two strings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Prob ...
随机推荐
- smarty插件开发代替注册插件方法registerPlugin
- 普通请求和ajax请求的区别
普通请求和ajax请求的区别? 下面的action返回一个json文件,文件内容为sts.*,data1
- f2fs解析(一)f2fs如何解决wandering tree
wandering tree问题是log-structured 文件系统(LFS) 特有的一个问题,因为LFS的脏数据是追加更新的,所以如果一个数据块变脏了,那么那个数据块的直接索引块.间接索引块都会 ...
- 10SpringMvc_springmvc快速入门小案例(注解版本)
第一步:新建案例工程:
- WPF使用cefsharp
最近在公司项目上会用到cefsharp.wpf,不知道为什么按照网上的配置一直无法运行成功,怎么配置可以参考以下这篇博文: http://www.cnblogs.com/TianFang/p/4573 ...
- 双绞线线序+POE供电网线
0 重点 一般情况下会用1236(橙白.橙.绿白.绿)传输数据,1.2用于发送,3.6用于接收,45(蓝.蓝白)电源正极 78(棕白.棕)电源负极. 一 网线线序 12发 36收 二 poe网线供电 ...
- unity触发器和碰撞器
Unity中检测碰撞的方法有两种,一种是触发器一种是碰撞器,现在我来解释一下两种的区别. 触发器:有三种方法,分别是OnTriggerEnter,OnTriggerStay,OnTriggerExit ...
- 微信开放平台,微信登陆第三方网站 提示redirect_uri 参数错误
在微信开放平台上我填写的回调域是:bbs.qiaoshisui.com/LoginApi/WeiXinCallBack,我构造的链接是:https://open.weixin.qq.com/conne ...
- Quartz.net打造信息抽取器
由于最近的一个项目需要定时抽取特定XML信息,然后保存到数据库,最后通过WebApi把手机端要使用的方法给暴露出来,所以去研究了一下Quartz.net.由于项目很小,我没用到Autofac,Repo ...
- JS 之DOM对象(1)
介绍DOM1中底层的一些属性和方法. 节点操作 appendChild() parentNode.appendChild(newNode) 在parentNode节点的最后插入newNode ins ...