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 ...
随机推荐
- 关于Yii2中count方法的使用
统计文章与分类中间表中c_id的数目,也就是category表中total字段的值 原生SQL语句:select count(c_id) from article_category where c_i ...
- js文本框提示和自动完成
1.模仿大型网站自动提示,就是输入“苹果”,在水果类中搜索,html代码如下: <div id="searchTips" style="display:none;w ...
- struts2验证框架1
<!--该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts 2处理.如果用户需要指定多个请求后缀,则多个后缀之间以英文逗 ...
- c# 调用打印机
1.本地打印机 //添加引用并using System.Management; public static void AvailablePrinters() { ManagementScope ms ...
- 【WPF】Winform调用WPF窗体注意事项
1.需要添加一些引用 2.调用处使用如下方法进行调用 Window win= new Window(); ElementHost.EnableModelessKeyboardInterop(win) ...
- 转载:关于 WebBrowser只对浏览器外应用程序以及在Internet Explorer 中以提升权限运行的应用程序启用
我是根据很多大神写的博客,以及我自己在做项目的时候做的关于提升Silverlight 中WebBrowser 提升信任的问题的总结: 1)选中Silverlight主程序,右键“属性”---“Sliv ...
- 如何设置word里的代码格式,使之有底纹的效果
1.测试平台:word2013 2.步骤:设计->底纹->填充->应用于->确定 3.效果:
- [CareerCup] 3.7 Adopt Animal 领养动物
3.7 An animal shelter holds only dogs and cats, and operates on a strictly "first in, first out ...
- 解答WPF中ComboBox SelectedItem Binding不上的Bug
正在做一个打印机列表,从中选择一个打印机(System.Printing) <ComboBox Width="150" ItemsSource="{Binding ...
- Core Data 使用
coredata使用了一种完全不同 的方法,你不需要创建类,而是在数据模型编辑器中创建一些实体,然后为这些实体创建托管对象. 实体由属性组成.有三种:特性:关系:提取属性. 使用键值编码来设置属性或检 ...