hdu_5507_GT and strings(AC自动机)
题意:给n个字符串和q个询问,每个询问给两个数字x,y,问1.x是否为y的子序列,2.x是否为y的子串,是输出1,否则输出0,每个询问输出2个数字
题解:
对于子序列,朴素的做法,每次询问的复杂度为max(str[x],str[y]),题目好像有数据卡这个做法,反正会T,正解应该是建立一个序列自动机,首先将所有的字符串连续存起来,用数组来保存每个字符串的位置,然后dp[i][j]表示第i个字符的下一个字符的位置,询问的时候就能做到复杂度为min(str[x],str[y])。、
对于子串,可以用AC自动机来预处理,子串的询问有点特别,不是一般的在树上走,而是对每个节点进行寻找,然后用map来记录关系,不过在询问的时候也有个优化,不加这个优化一样会T,加了瞬间变成170+ms,具体看代码。
#include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef pair<int,int>P; const int N=1e5+;
int t,n,m,L[N],R[N],loc[N],dp[N][],Q[N][],ans[N][];
char str[N];
map<P,int>ok;
const int AC_N=N,tyn=;//数量乘串长,类型数
struct AC_automation{
int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot;
inline int getid(char x){return x-'a';}
void nw(){cnt[++tot]=,fail[tot]=;memset(tr[tot],,sizeof(tr[tot]));}
void init(){tot=-,fail[]=-,nw();}
void insert(int l,int r,int x=){
for(int i=l,w;i<=r;x=tr[x][w],loc[i]=x,i++)
if(!tr[x][w=getid(str[i])])nw(),tr[x][w]=tot;
cnt[x]++;//串尾标记
}
void build(int head=,int tail=){
for(int i=;i<tyn;i++)if(tr[][i])Q[++tail]=tr[][i];
while(head<=tail)for(int x=Q[head++],i=;i<tyn;i++)
if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i];
else tr[x][i]=tr[fail[x]][i];
}
void ask(int l,int r)
{
F(i,l,r)for(int p=loc[i];p;p=fail[p])
if(cnt[p])ok[P(p,loc[r])]=;
else if(fail[p]&&!cnt[fail[p]])fail[p]=fail[fail[p]];//决定是否T的优化
}
}AC; void work1()
{
F(i,,)dp[R[n]+][i]=N;//建立“子序列自动机”
for(int i=R[n];i>=;i--)F(j,,)
if(str[i]==j+'a')dp[i][j]=i;
else dp[i][j]=dp[i+][j];
F(i,,m)
{
int x=Q[i][],y=Q[i][];
if(R[x]-L[x]>R[y]-L[y])ans[i][]=;
else
{
ans[i][]=;
for(int j=L[x],p=L[y];j<=R[x];j++,p++)
{
p=dp[p][str[j]-'a'];
if(p>R[y]){ans[i][]=;break;}
}
}
}
} void work2()
{
AC.init(),ok.clear();
F(i,,n)AC.insert(L[i],R[i]);
AC.build();
F(i,,n)AC.ask(L[i],R[i]);
F(i,,m)ans[i][]=ok[P(loc[R[Q[i][]]],loc[R[Q[i][]]])];
} int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int ed=;
F(i,,n)
{
scanf("%s",str+ed);
int len=strlen(str+ed);
L[i]=ed,R[i]=ed+len-,ed=R[i]+;
}
F(i,,m)scanf("%d%d",&Q[i][],&Q[i][]);
work1(),work2();
F(i,,m)printf("%d%d",ans[i][],ans[i][]);
puts("");
}
return ;
}
hdu_5507_GT and strings(AC自动机)的更多相关文章
- SPOJ 7758. Growing Strings AC自动机DP
Growing Strings 题目:给出n个字符串,问最多能够选出多少个串组成序列,并满足前一个字符串是后一个字符串的子串. 分析: AC自动机经典水题... 考虑每个节点结尾时,他能够选出最多的串 ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- 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 6208 The Dominator of Strings【AC自动机/kmp/Sunday算法】
Problem Description Here you have a set of strings. A dominator is a string of the set dominating al ...
- The Dominator of Strings HDU - 6208(ac自动机板题)
题意: 就是求是否有一个串 是其它所有串的母串 解析: 把所有的串都加入到trie数中 然后用最长的串去匹配就好了 emm..开始理解错题意了...看成了只要存在一个串是另一个的母串就好.. 然后输 ...
- HDU - 6208 The Dominator of Strings HDU - 6208 AC自动机 || 后缀自动机
https://vjudge.net/problem/HDU-6208 首先可以知道最长那个串肯定是答案 然后,相当于用n - 1个模式串去匹配这个主串,看看有多少个能匹配. 普通kmp的话,每次都要 ...
- AC自动机-算法详解
What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...
- 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组
F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...
随机推荐
- linux上安装Jmeter
一.首先,你的linux上要有jdk,没有的话请参考上一篇 http://www.cnblogs.com/bigshan-1/p/6242991.html 二.延续上篇的linux用户xiaoming ...
- Java 并发 线程同步
Java 并发 线程同步 @author ixenos 同步 1.异步线程本身包含了执行时需要的数据和方法,不需要外部提供的资源和方法,在执行时也不关心与其并发执行的其他线程的状态和行为 2.然而,大 ...
- jquery ColorPicker 颜色选择器
$(function() { $('#colorpickerField').ColorPicker({ onSubmit: function(hsb, hex, rgb, el) { $(el).va ...
- MIT线性代数课程 总结与理解-第一部分
概述 个人认为线性代数从三个角度,或者说三个工具来阐述了线性关系,分别是: 向量 矩阵 空间 这三个工具有各自的一套方法,而彼此之间又存在这密切的联系,通过这些抽象出来的工具可以用来干一些实际的活,最 ...
- JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解
Jmap是一个可以输出所有内存中对象的工具,甚至可以将VM 中的heap,以二进制输出成文本.打印出某个java进程(使用pid)内存内的,所有'对象'的情况(如:产生那些对象,及其数量). 使用方法 ...
- C#如何实现url短地址?C#短网址压缩算法与短网址原理入门
c# url短地址压缩算法与短网址原理的例子,详细介绍了短网址的映射算法,将长网址md5生成32位签名串,分为4段,每段8个字节,然后生成短网址,具体见文本实例. 短网址映射算法: 将长网址md5生成 ...
- 移动端 web开发心得
吐槽:华为p9 内置浏览器就是个渣,各种奇葩的bug,1.如果将一个输入框的最大长度设为4,然后输入4个后,js将输入的值置空,就无法再输入了 手机上浏览器比较蛋疼的是,点击一个输入框,输入法将页面挡 ...
- 关于数据汇总方面返回Json数据的小小心得
在一开始的开发中,计算好相关数据,然后通过 1.拼串 2.实例化Dictory对象再通过JavaScriptSerializer转换为json. 其中,2只适合于二维数据.1适合多维数据,但拼串比较费 ...
- redis整合spring
最近公司项目有用到 所以找了一下实例.感觉很清晰. 完整项目路径http://www.cnblogs.com/dennisit/p/3614521.html看了一下应该没问题
- oracle查询排序后的前几条记录
select * from (select * from table order by 字段名 desc) where rownum<你要查的记录条数,这样才能符合条件.