bzoj2746 [HEOI2012]旅行问题 ( AC自动机 & fail树 +lca + hash )
来源:互联网 发布:数据结构课程设计java 编辑:程序博客网 时间:2024/05/18 00:03
bzoj2746 [HEOI2012]旅行问题
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2746
题意:
给定n个字符串,共有m次询问,每次询问输入四个数S1,L1,S2,L2,表示求第S1个字符串长度为L1的前缀,和第S2个字符串长度为L2的前缀,的最长公共后缀,满足这个后缀是给定的某一个串的前缀。
为了不使输出过大,你只需把这个字符串按照如下生成的26进制数转成10进制后mod 1000000007后输出:
a->0
b->1
…
z->25
比如cab被编码成2 * 26^2 + 0 * 26^1 + 1 * 26^0 = 1353。
数据范围
m,n<=1000000;
保证输入文件不超过20MB。
题解:
fail树的应用。
两个串的最长公共后缀就是他们在fail树上的lca。
输入时把每个字符串插入Trie树时,顺便保存每个位置26进制后的值,以及每个位置对应Trie树上点的编号。
求fail时就干脆向倍增求lca一样,fail[u][p]就是u点向上跳2^p步得到的点。
最后直接输出lca的26进制hash值。
刚好100行☆
代码:
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<queue>#define LL long longusing namespace std;const int N=1<<20;const int mod=1000000007;const int P=21;queue<int> Q;int n,m,ch[N][26],fail[N][25],dep[N],tail=0,cnt=0,pos[N<<1],lenth[N];char str[N];LL Hash[N];void insert(){ int len=strlen(str); int p=0; LL mark=0; for(int i=0;i<len;i++) { int c=str[i]-'a'; if(!ch[p][c]) { ch[p][c]=++tail; Hash[ch[p][c]]=(((Hash[p]*26)%mod)+c)%mod; } pos[++cnt]=ch[p][c]; p=ch[p][c]; } }void getfail(){ dep[0]=0; for(int i=0;i<26;i++) if(ch[0][i]) { fail[ch[0][i]][0]=0; dep[ch[0][i]]=1; Q.push(ch[0][i]); } while(!Q.empty()) { int top=Q.front(); Q.pop(); for(int i=0;i<26;i++) { if(!ch[top][i]) { ch[top][i]=ch[fail[top][0]][i]; continue; } int u=ch[top][i]; fail[u][0]=ch[fail[top][0]][i]; dep[u]=dep[fail[u][0]]+1; for(int j=1;j<P;j++) fail[u][j]=fail[fail[u][j-1]][j-1]; Q.push(u); } } }int getlca(int u,int v){ if(dep[u]<dep[v]) swap(u,v); int d=dep[u]-dep[v]; for(int i=0;d;d>>=1,i++) if(d&1) u=fail[u][i]; if(u==v) return u; for(int p=P-1;p>=0;p--) { if(fail[u][p]!=fail[v][p]) { u=fail[u][p]; v=fail[v][p]; } } return fail[u][0];}int main(){ scanf("%d",&n); memset(fail,0,sizeof(fail)); lenth[0]=0; for(int i=1;i<=n;i++) { scanf("%s",str); insert(); lenth[i]=strlen(str); lenth[i]+=lenth[i-1]; } getfail(); scanf("%d",&m); while(m--) { int p1,l1,p2,l2; scanf("%d%d%d%d",&p1,&l1,&p2,&l2); int t1=pos[lenth[p1-1]+l1]; int t2=pos[lenth[p2-1]+l2]; int lca=getlca(t1,t2); printf("%lld\n",Hash[lca]); } return 0;}
阅读全文
0 0
- bzoj2746 [HEOI2012]旅行问题 ( AC自动机 & fail树 +lca + hash )
- [BZOJ2746]-[HEOI2012]旅行问题-fail树+倍增LCA
- BZOJ 2746 旅行问题 (fail树 Hash LCA)
- bzoj2746 旅行问题
- bzoj3172 AC自动机+fail树
- HDU6096 ac自动机+fail树
- HEOI 2012 旅行问题 BZOJ2746
- 2746: [HEOI2012]旅行问题
- AC自动机 fail树 线段树维护
- 【bzoj3172】[Tjoi2013]单词 AC自动机+fail树
- bzoj3172 ac自动机fail树应用
- [AC自动机][fail树] bzoj3172 单词
- [AC自动机][fail树][BZOJ 3172][TJOI2013]单词
- 关于维护AC自动机fail树的三道题目
- AC自动机相关Fail树和Trie图相关基础知识
- BZOJ 3172 [Tjoi2013]单词 AC自动机(fail树)
- bzoj2434 ac自动机+fail树+Dfs序+树状数组
- [BZOJ3172][TJOI2013]单词(AC自动机+fail树)
- Linux(Red Hat6.5)下安装svn服务器,并通过http访问
- 图像处理的仿射变换和透视变换
- 第三章 创建Zookeeper会话【下】
- 3DES加密算法
- Artificial Neural Networks: Mathematics of Backpropagation (Part 4)
- bzoj2746 [HEOI2012]旅行问题 ( AC自动机 & fail树 +lca + hash )
- EasyGUI的安装
- Bean
- 如何发表期刊方法步骤
- QUESTIONS
- android初探
- com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value:
- 利用apidoc维护api接口文档
- 利用MySQL-Front生成sql字典