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 ...
随机推荐
- 时间与NSString转换
//传进来时间字符串转换 + (NSString *) getChatTimeString:(NSString *)timeString { if (timeString==nil || timeSt ...
- linux如何挂载windows下的共享文件
说明:windows下有一共享文件夹APP,windows本地ip是192.168.9.155现在需要在linux服务器上挂载这个APP文件夹,linux服务器ip是192.168.9.200 操作记 ...
- Xcode6与Xcode5中沙盒的变动以及偏好设置目录的变动
1.Xcode6模拟器路径与Xcode5模拟器路径对比: (1)Xcode5中模拟器路径为:/Users/用户名/Library/Application Support/iPhone Simulato ...
- 在WebApi中实现Cors访问
Cors是个比较热的技术,这在蒋金楠的博客里也有体现,Cors简单来说就是“跨域资源访问”的意思,这种访问我们指的是Ajax实现的异步访问,形象点说就是,一个A网站公开一些接口方法,对于B网站和C网站 ...
- [CareerCup] 9.1 Climbing Staircase 爬楼梯
9.1 A child is running up a staircase with n steps, and can hop either 1 step, 2 steps, or 3 steps a ...
- [MetaHook] R_SparkStreaks
By hzqst void R_SparkStreaks(vec_t *pos, int count, int velocityMin, int velocityMax) { int i; parti ...
- Opencv step by step - 加载视频
刚买了本 "学习Opencv" 这本书,慢慢看起来. 一开始就是加载视频了.当然了,首先你要有个视频 从这里下载了一个: tan@ubuntu:~$ wget http://www ...
- [原创]Net实现Excel导入导出到数据库(附源码)
关于数据库导出到Excel和SQLServer数据导出到Excel的例子,在博客园有很多的例子,自己根据网上搜集资料,自己做了亦歌简单的demo,现在分享出来供初学者学习交流使用. 一.数据库导入导出 ...
- Android--按钮点击事件
Android中Button的点击事件非常简单,主要是一个内部类的问题 在界面上存在两个按钮和一个文本框,点击不同按钮的时候文本框中显示不同按钮的文字信息 <?xml version=" ...
- OpenCart 最新使用教学视频合集
OpenCart 是一个很火的开源电商系统,国内越来越多的人开始使用 OpenCart 搭建自己的电商网站.OpenCart 的功能非常强大,当然功能也非常多.这里整理了 OpenCart 最重要的一 ...