题目链接:hdu_5507_GT and strings

题意:给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自动机)的更多相关文章

  1. SPOJ 7758. Growing Strings AC自动机DP

    Growing Strings 题目:给出n个字符串,问最多能够选出多少个串组成序列,并满足前一个字符串是后一个字符串的子串. 分析: AC自动机经典水题... 考虑每个节点结尾时,他能够选出最多的串 ...

  2. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  3. hdu 6208 The Dominator of Strings【AC自动机】

    hdu 6208 The Dominator of Strings[AC自动机] 求一个串包含其他所有串,找出最长串去匹配即可,但是匹配时要对走过的结点标记,不然T死QAQ,,扎心了.. #inclu ...

  4. HDU 6208 The Dominator of Strings(AC自动机)

    The Dominator of Strings Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java ...

  5. 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 ...

  6. The Dominator of Strings HDU - 6208(ac自动机板题)

    题意: 就是求是否有一个串 是其它所有串的母串 解析: 把所有的串都加入到trie数中  然后用最长的串去匹配就好了 emm..开始理解错题意了...看成了只要存在一个串是另一个的母串就好.. 然后输 ...

  7. HDU - 6208 The Dominator of Strings HDU - 6208 AC自动机 || 后缀自动机

    https://vjudge.net/problem/HDU-6208 首先可以知道最长那个串肯定是答案 然后,相当于用n - 1个模式串去匹配这个主串,看看有多少个能匹配. 普通kmp的话,每次都要 ...

  8. AC自动机-算法详解

    What's Aho-Corasick automaton? 一种多模式串匹配算法,该算法在1975年产生于贝尔实验室,是著名的多模式匹配算法之一. 简单的说,KMP用来在一篇文章中匹配一个模式串:但 ...

  9. 【Codeforces710F】String Set Queries (强制在线)AC自动机 + 二进制分组

    F. String Set Queries time limit per test:3 seconds memory limit per test:768 megabytes input:standa ...

随机推荐

  1. trove 开发者阅读翻译

    介绍 Trove为OpenStack提供数据库的服务.它的设计运行完全符合OpenStack,目标是让用户能快速.轻松地利用关系数据库的特点,没有负担的处理复杂的管理任务.云用户和数据库管理员可以根据 ...

  2. Egret 显示容器

    1,显示容器:所有的容器都继承自DisplayObjectContainer , DisplayObjectContainer 又继承自DisplayObject: 2,想定义一个容器只要创建一个类, ...

  3. android屏幕适配之度量单位、屏幕分类、图标尺寸归类分析

    好久没有做android项目UI的适配了,好多基本概念都已经模糊了,于是萌生了将屏幕分辨率.常用单位.常用图标尺寸等信息规整的想法,一下就是通过查询资料,自己验证的一些随笔,如有失误之处,望大家及时予 ...

  4. intellij 出现“Usage of API documented as @since 1.6+”的解决办法

    Usage of API documented as @since 1.6+ This inspection finds all usages of methods that have @since ...

  5. iScroll 下 a 标签失效

    遇到个莫名其妙的问题,iScroll 下的 a 标签点击没有反应了,不管怎么调整 z-index 都无效果,很是无语. 查找半天后找到解决方法: $(function(){ new IScroll(' ...

  6. js数组操作-找出一组按不同顺序排列的字符串的数组元素

    从一组数组中找出一组按不同顺序排列的字符串的数组元素将字符串转换成数组后再对数组进行 sort 排序,abcd 和 bdca 使用 sort 排序后会变成 abcd,将拍好序的字符串作为对象的 key ...

  7. ajax中的stasus错误详解

    一.英文版解析 0: (Uninitialized) the send( ) method has not yet been invoked. 1: (Loading) the send( ) met ...

  8. Egret 学习之 入口函数 及开始编写程序(三)

    1,Egret的程序入口: C和java是以一个main函数作为入口,但egret类似于ActionScript 是以一个文档类作为入口,确切的说是以这个文档类的构造函数作为入口: 2,文档类的构造函 ...

  9. hdu 2149 Public Sale 简单博弈

    Problem Description 虽然不想,但是现实总归是现实,Lele始终没有逃过退学的命运,因为他没有拿到奖学金.现在等待他的,就是像FarmJohn一样的农田生涯.要种田得有田才行,Lel ...

  10. 使用SQL Server视图的优缺点

    SQL Server视图我们经常会用的到,下面就为您介绍使用SQL Server视图的优缺点,希望可以对您SQL Server视图有更多的了解. 在程序设计的时候必须先了解视图的优缺点,这样可以扬长避 ...