题意

给定 \(n\) 个字符串,\(m\) 个询问,每次询问 \(a\) 字符串的后缀和 \(b\) 字符串的前缀最多能匹配多长。

\(1\leq n,m \leq 10^5\)

思路

多串匹配,考虑 \(\text{AC}\)自动机,对 \(n\) 个串建自动机,观察这个结构,不难发现 \(Trie\) 树的结构和前缀有关,\(fail\) 树的结构和后缀有关。

考虑离线,对于每个 \(b\) ,存储它对应的 \(a\) ,我们通过在自动机上扫 \(b\) 来回答。由于扫到某节点 \(u\) ,在 \(fail\) 树上 \(u\) 的子节点都能得到 \(u\) 在 \(Trie\) 树上深度的贡献,最后对每一个 \(a\),查询它在自动机位置上的贡献最大值即可 。用线段树维护 \(fail\) 树的 \(\text{dfs}\) 序,区间修改最大值,单点查询最大值。

\(\text{AC}\)自动机上有 \(Trie,fail\) 两棵树,分别包含前后缀的信息,这类问题可以通过 \(\text{AC}\)自动机,转化为树上问题。

代码

#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
#define x first
#define y second
typedef long long LL;
using namespace std;
typedef pair<int,int> pii;
const int N=1e5+5;
const int NN=N*22;
int c_d[256];
template<const int maxn,const int maxm>struct Linked_list
{
int head[maxn],to[maxm],nxt[maxm],tot;
Linked_list(){clear();}
void clear(){memset(head,-1,sizeof(head));tot=0;}
void add(int u,int v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}
#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
struct SegmentTree
{
int lson[NN],rson[NN],tag[NN];
int rt,tot;
void build()
{
tag[0]=lson[0]=rson[0]=0;
rt=tot=0;
}
void create(int &k)
{
if(!k)
{
k=++tot;
tag[k]=lson[k]=rson[k]=0;
}
}
void update(int &k,int L,int R,int val,int l,int r)
{
create(k);
if(L<=l&&r<=R){tag[k]=max(tag[k],val);return;}
int mid=(l+r)>>1;
if(L<=mid)update(lson[k],L,R,val,l,mid);
if(R>mid)update(rson[k],L,R,val,mid+1,r);
}
int query(int k,int x,int l,int r)
{
if(l==r)return tag[k];
int mid=(l+r)>>1;
if(x<=mid)return max(query(lson[k],x,l,mid),tag[k]);
else return max(query(rson[k],x,mid+1,r),tag[k]);
}
}ST;
Linked_list<N,N>G;
int L[N],R[N],ord;
int ch[N][4],f[N],dep[N];
string P[N];
int rt,tot;
vector<pii>Qry[N];int Ans[N];
char str[N];
int idx[N];
int n,q; void build(){rt=tot=0;}
void create(int &k)
{
if(!k)
{
k=++tot;
FOR(i,0,3)ch[k][i]=0;
}
}
void insert(int &k,string &str,int id)
{
create(k);
int now=k;dep[now]=0;
FOR(i,0,str.length()-1)
{
create(ch[now][c_d[(int)str[i]]]);
now=ch[now][c_d[(int)str[i]]];
dep[now]=i+1;
}
idx[id]=now;
}
void get_fail()
{
queue<int>Q;
while(!Q.empty())Q.pop();
f[rt]=rt;
FOR(i,0,3)
{
if(ch[rt][i])f[ch[rt][i]]=rt,Q.push(ch[rt][i]);
else ch[rt][i]=rt;
}
while(!Q.empty())
{
int u=Q.front();Q.pop();
FOR(i,0,3)
{
if(ch[u][i])f[ch[u][i]]=ch[f[u]][i],Q.push(ch[u][i]);
else ch[u][i]=ch[f[u]][i];
}
}
}
void dfs_fail(int u)
{
L[u]=++ord;
EOR(i,G,u)dfs_fail(G.to[i]);
R[u]=ord;
}
void query(int k,string &str,vector<pii>&vec)
{
ST.build();
int now=k;
ST.update(ST.rt,L[now],R[now],dep[now],1,tot);
FOR(i,0,str.length()-1)
{
now=ch[now][c_d[(int)str[i]]];
ST.update(ST.rt,L[now],R[now],dep[now],1,tot);
}
FOR(i,0,(int)vec.size()-1)Ans[vec[i].y]=ST.query(ST.rt,vec[i].x,1,tot);
} int main()
{
c_d[(int)'A']=0,c_d[(int)'C']=1,c_d[(int)'G']=2,c_d[(int)'T']=3;
while(~scanf("%d%d",&n,&q))
{
G.clear(),build();
FOR(i,1,n)Qry[i].clear();
FOR(i,1,n)
{
cin>>P[i];
insert(rt,P[i],i);
}
get_fail();
FOR(i,1,tot)if(f[i]!=i)G.add(f[i],i);
ord=0;dfs_fail(rt); FOR(i,1,q)
{
int a,b;
scanf("%d%d",&a,&b);
Qry[b].push_back(pii(L[idx[a]],i));
}
FOR(i,1,n)query(rt,P[i],Qry[i]);
FOR(i,1,q)printf("%d\n",Ans[i]);
}
return 0;
}

HDU 5069 Harry And Biological Teacher(AC自动机+线段树)的更多相关文章

  1. hdu 4117 -- GRE Words (AC自动机+线段树)

    题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ...

  2. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  3. BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)

    Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...

  4. HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)

    Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the mos ...

  5. 背单词(AC自动机+线段树+dp+dfs序)

    G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较   题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ...

  6. 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  7. 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  8. hdu 5266 pog loves szh III(lca + 线段树)

    I - pog loves szh III Time Limit:6000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I ...

  9. BZOJ3413: 匹配(后缀自动机 线段树合并)

    题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ...

随机推荐

  1. ASP.Net 获取Form表单值

    新建一HtmlPage1.html,如下post发送() <body> <form enctype="multipart/form-data" action=&q ...

  2. Eclipse创建maven工程后没有build path解决方案

    1.修改maven工程下的.project文件为如下内容 <?xml version="1.0" encoding="UTF-8"?> <pr ...

  3. Fabric架构:抽象的逻辑架构与实际的运行时架构

    Fabric从1.X开始,在扩展性及安全性上面有了大大的提升,且新增了诸多的新特性: 多通道:支持多通道,提高隔离安全性. 可拔插的组件:支持共识组件.权限管理组件等可拔插功能. 账本数据可被存储为多 ...

  4. 文字列大好きいろはちゃんイージー / Iroha Loves Strings (ABC Edition) (优先队列)

    题目链接:http://abc042.contest.atcoder.jp/tasks/abc042_b Time limit : 2sec / Memory limit : 256MB Score ...

  5. Caddy – 方便够用的 HTTPS server 新手教程

    最近发现了一个 golang 开发的 HTTP server,叫做 Caddy,它配置起来十分简便,甚至可以 28 秒配置好一个支持 http2 的 server ,而且对各种 http 新特性都支持 ...

  6. maven 项目 查询部分关心的字段

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC ...

  7. 用到临时表空间的几种SQL

    用到临时表空间的几种SQL CREATE INDEX SELECT ... ORDER BY SELECT DISTINCT ... SELECT ... GROUP BY SELECT ... UN ...

  8. spring boot log4j2与三方依赖库log4j冲突无法初始化问题解决方法

    因为从Spring Boot 1.4开始,spring boot就不支持log4j了,必须是log4j2或者logback,具体两者如何配置以及NDC的支持可以参考spring boot精华版. 这里 ...

  9. ora-904 rowid create materialized view

    create materialized view t_v asselect t1.*,1 as marker,rowid from t1 t1union allselect t2.*,2 as mar ...

  10. 阿里云端口失效导致tomcat无法对外提供服务

    下午,我们一个环境启动成功,但是却无法访问,经查看启动日志,如下: Mar 23, 2017 2:15:09 PM org.apache.coyote.http11.AbstractHttp11Pro ...