HDU 5069 Harry And Biological Teacher(AC自动机+线段树)
题意
给定 \(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自动机+线段树)的更多相关文章
- hdu  4117 -- GRE Words (AC自动机+线段树)
		题目链接 problem Recently George is preparing for the Graduate Record Examinations (GRE for short). Obvi ... 
- hdu 4117 GRE Words (ac自动机 线段树 dp)
		参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ... 
- BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)
		Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ... 
- HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)
		Recently George is preparing for the Graduate Record Examinations (GRE for short). Obviously the mos ... 
- 背单词(AC自动机+线段树+dp+dfs序)
		G. 背单词 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使 ... 
- 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)
		[BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ... 
- 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)
		[BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ... 
- hdu 5266 pog loves szh III(lca + 线段树)
		I - pog loves szh III Time Limit:6000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I ... 
- BZOJ3413: 匹配(后缀自动机 线段树合并)
		题意 题目链接 Sol 神仙题Orz 后缀自动机 + 线段树合并... 首先可以转化一下模型(想不到qwq):问题可以转化为统计\(B\)中每个前缀在\(A\)中出现的次数.(画一画就出来了) 然后直 ... 
随机推荐
- 【转】SQL Server 运行状况监控SQL语句
			SQL Server 运行状况监控SQL语句 Microsoft SQL Server 2005 提供了一些工具来监控数据库.方法之一是动态管理视图.动态管理视图 (DMV) 和动态管理函数 (D ... 
- 【2017-04-17】类库、通用变量、is和as、委托
			类库dll文件,里边有很多被编译后的C#代码,不可阅读,不可修改,只能调用 1.类库创建 新建项目为类库,类库文件编写完成后,选择生成—生成解决方案,在debug文件夹下找到dll文件 2.类库引用 ... 
- 【2017-03-20】HTML基础知识,标记,表格,表格嵌套及布局,超链接
			一.HTML 网站(站点),网页基础知识 HTML是一门编程语言的名字:超文本标记语言 可以理解为:超越了文本的范畴,可以有图片.视频.音频.动画特效等其他内容,用标记的方法进行编程的计算机语言 基 ... 
- Vue.js是什么,vue介绍
			Vue.js是什么,vue介绍 Vue.js 是什么Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用. ... 
- eclipse  依赖别的 工程  断点进不去
			maven Debug 发现进不了断点. 点击右键-->Properties-->Java Compiler-->Classfile Generation, 勾选上Add line ... 
- jenkins2
			创建工程 Eclipse创建工程:注意工程的路径,不是/home/svn,这个是svn的根目录. 是工程上传的路径,Apple直接下面有pom文件. 创建工程,创建一个任务就是创建一个工程. 需要注意 ... 
- Bluetooth_FTP_SPEC: 蓝牙FTP介绍
			FTP(Bluetooth File Transfer Profile) defines howfolders and files on a server device can be browsed ... 
- 移植并修改成功的模拟iic读写EEPROM at24c02
			2010-04-24 12:58:00 注:如果要读24c128或264,地址位为16位的.现在的地址位为8位. protues仿真图 源程序如下: #include <iom16v.h> ... 
- HDU 1846 Brave Game (巴什博弈)
			题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1846 十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫<勇敢者的游戏& ... 
- 前端异步的一种方法库:axios
			关于axios,其实原本在做开发的几年里并不知道,一直使用的也都是jquery的ajax.后来因为一个同事的述说,我才知道有这么个库,基于promise的http库. 看来,以前的我确实比较井底之蛙了 ... 
