2746: [HEOI2012]旅行问题

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 489  Solved: 174
[Submit][Status][Discuss]

Description

yz是Z国的领导人,他规定每个地区的名字只能为26个小写拉丁字母的一个。由于地 区数有可能超过26个,便产生了一个问题,如何辨别名字相同的地区?于是yz规定,一个 地区的描述必须包含它的所有上级,且上级按次序排列。于是,一个地区的描述是一个字符 串。比如说,一个地区的名字为c,它的上级为b,b的上级为a,a没有上级,那么这个地 区就描述为abc。显然,这个描述同时包含了c的上级b和b的上级a的描述,分别为ab和a。 值得注意的是,每个地区最多有一个上级,同一上级的地区之间名字不同,没有上级的 地区之间名字不同。现在,yz对外公布了n个地区的描述,这些描述中包含了Z国所有地区的描述,并让 你处理来访者的旅行问题。现有m对人访问这个国家,对于每对人,第一个人喜欢第i个描述中的第j个地区,设 这个地区描述为s1,第二个人喜欢第k个描述中的第l个地区,设这个地区描述为s2。他们为了统一行程,决定访问描述为s的地区(显然他们只关心地区的名字,并非是地区本身), 设s的长度为t,s需要满足以下条件: 
1:t<=j, t<=l; 
1:s[1..t] = s1[j-t+1 … j], s[1..t] = s2[l-t+1 … l];(即s为s1中1到k位 与s2中1到l位的公共后缀) 
2:t最大化。 
为了不使输出过大,你只需把这个字符串按照如下生成的26进制数转成10进制后mod 1000000007后输出: 
a->0 
b->1 



z->25 
比如地区cab被编码成2 *    26? + 0 * 26? + 1 * 26? = 1353。

Input

第一行给定一个整数n 
第2…n+1行:每i+1行给定一个字符串a[i],表示第i个描述。 
接下来一行一个整数m 
接下来m行:每行给定四个整数i,j,k,l,字母含义与题目描述一致。

Output

共m行,每行一个整数,表示答案字符串的编码。

Sample Input

2
aabb babb
2
1 3 2 3
1 4 2 4

Sample Output

1
1
【样例说明】
询问1中的公共后缀有ab和b,但是没有ab这个地区,只有b地区,所以只能选择b这个 地区;
询问2中的公共后缀有abb、bb和b,但是没有abb和bb这两个地区,只有b地区,所以 只能选择b这个地区。

HINT

【数据范围】

设这个国家地区总数数为tot(注意:输入的字符串总长度可能超过tot!) 对于30%的数据,满足tot,m,n<=100;

对于50%的数据,满足tot,m,n<=1000;

对于80%的数据,满足tot,m,n<=100000;

对于100%的数据,满足tot,m,n<=1000000;

保证输入文件不超过20MB。

  fail树建出来,查询两点间lca

  这道题没什么好说的,丧心病狂的卡空间,卡常数,由于链表数组少开了一倍,导致RE,还以为是字符数组必须开到2*1e6的大小,然后连trie树指针都优化成了链表,虽然这优化确实没有什么用,但是把空间给降下来了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define MAXN 1000010
#define MAXV MAXN
#define MAXE MAXV
#define MAXLEN 20*1024*1024
#define MOD 1000000007
typedef long long qword;
inline int nextInt()
{
register int x=;
register char ch;
while (ch=(char)getchar(),ch<'' || ch>'');
while (x=x*+ch-'',ch=(char)getchar(),ch<='' && ch>='');
return x;
}
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXV];
int tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
}
struct TEdge
{
int idx,ptr;
TEdge *next;
}TE[MAXN];
int topte=-;
struct trie_node
{
TEdge *nxt;
int fail;
int hash;
}trie[MAXN];
int root=;
int topt=;
void Add_trie(char *str,int *ptr)
{
TEdge *ne;
int now=root;
int hash=;
bool flag;
while (*str)
{
hash=(int)(((qword)hash*+*str-'a')%MOD);
int idx=*(str++)-'a';
flag=false;
for (ne=trie[now].nxt;ne;ne=ne->next)
{
if (ne->idx==idx)
{
flag=true;
now=ne->ptr;
}
}
if (!flag)
{
TE[++topte].idx=idx;
TE[topte].ptr=++topt;
TE[topte].next=trie[now].nxt;
trie[now].nxt=&TE[topte];
now=TE[topte].ptr;
}
trie[now].hash=hash;
*(ptr++)=now;
}
}
int q[MAXN];
void Build_AC()
{
int head=-,tail=;
int now;
trie[root].fail=root;
q[]=root;
now=q[++head];
TEdge *tne,*tn2;
for (tne=trie[root].nxt;tne;tne=tne->next)
{
trie[tne->ptr].fail=root;
q[++tail]=tne->ptr;
}
while (head<tail)
{
now=q[++head];
for (tne=trie[now].nxt;tne;tne=tne->next)
{
for (int j=trie[now].fail;j!=root;j=trie[j].fail)
{
for (tn2=trie[j].nxt;tn2;tn2=tn2->next)
{
if (tn2->idx==tne->idx)
{
trie[tne->ptr].fail=tn2->ptr;
break;
}
}
if (trie[tne->ptr].fail)break;
}
if (!trie[tne->ptr].fail)
for (tn2=trie[root].nxt;tn2;tn2=tn2->next)
if (tn2->idx==tne->idx)
trie[tne->ptr].fail=tn2->ptr;
q[++tail]=tne->ptr;
}
}
for (int i=;i<=tail;i++)
{
now=q[i];
addedge(trie[now].fail,now);
}
} char str[MAXLEN];
int ptr[MAXLEN];
int shead[MAXN];
struct Link
{
int val,id;
Link *next;
}LE[MAXN*],*LK[MAXN];
int topl=-;
inline void addlink(int x,int y,int id)
{
LE[++topl].val=y;
LE[topl].id=id;
LE[topl].next=LK[x];
LK[x]=&LE[topl];
}
int stack[MAXN];
bool vis[MAXN];
int uf[MAXN];
int res[MAXN];
int get_fa(int now)
{
return uf[now]==now ? now : uf[now]=get_fa(uf[now]);
}
void dfs(int now)
{
int tops=-;
Edge *ne;
Link *nl;
stack[++tops]=now;
while (~tops)
{
if (stack[tops]<)
{
now=-stack[tops--];
uf[get_fa(now)]=get_fa(trie[now].fail);
}else
{
now=stack[tops];
vis[now]=true;
for (nl=LK[now];nl;nl=nl->next)
{
if (vis[nl->val])
{
res[nl->id]=trie[get_fa(nl->val)].hash;
}
}
if (!stack[tops])
tops--;
else
stack[tops]=-stack[tops];
for (ne=V[now];ne;ne=ne->next)
{
stack[++tops]=ne->np;
}
}
}
} int main()
{
freopen("input.txt","r",stdin);
int n;
scanf("%d\n",&n);
for (int i=;i<n;i++)
{
scanf("%s",str+shead[i]);
Add_trie(str+shead[i],ptr+shead[i]);
shead[i+]=shead[i]+strlen(str+shead[i]);
}
Build_AC();
int m;
int x,y;
scanf("%d",&m);
int a,b,c,d;
for (int i=;i<m;i++)
{
a=nextInt();b=nextInt();c=nextInt();d=nextInt();
a--,b--,c--,d--;
x=ptr[shead[a]+b];
y=ptr[shead[c]+d];
addlink(x,y,i);
addlink(y,x,i);
}
for (int i=;i<=topt;i++)
uf[i]=i;
dfs();
for (int i=;i<m;i++)
printf("%d\n",res[i]);
}

bzoj 2746: [HEOI2012]旅行问题 AC自动机fail树的更多相关文章

  1. (RERERERERERERERERERERE) BZOJ 2746: [HEOI2012]旅行问题

    二次联通门 : BZOJ 2746: [HEOI2012]旅行问题 神TM STL的vector push_back进一个数后取出时就变成了一个很小的负数.. 调不出来了, 不调了 #include ...

  2. BZOJ 2746: [HEOI2012]旅行问题

    2746: [HEOI2012]旅行问题 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 921  Solved: 291[Submit][Status ...

  3. BZOJ2746: [HEOI2012]旅行问题(AC自动机 LCA)

    Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1188  Solved: 383[Submit][Status][Discuss] Descripti ...

  4. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  5. BZOJ 3172: [Tjoi2013]单词 [AC自动机 Fail树]

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 3198  Solved: 1532[Submit][Status ...

  6. BZOJ 2905: 背单词 AC自动机+fail树+dfs序+线段树

    Description 给定一张包含N个单词的表,每个单词有个价值W.要求从中选出一个子序列使得其中的每个单词是后一个单词的子串,最大化子序列中W的和. Input 第一行一个整数TEST,表示数据组 ...

  7. BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树

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

  8. 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2022  Solved: 1158[Submit][Sta ...

  9. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

随机推荐

  1. linux atime ctime mtime

    touch testtime 1. stat testtime[为文件名] 可以查看这个文件名的三者状态 2.ll testtime;ll --time=atime testtime ;ll --ti ...

  2. html笔记04:在html之中导入css两种常见方法

    1.导入式: <html> <head> <title></title> <style type="text/css"> ...

  3. Flex学习教程网站地址

    http://www.985school.com/flex/complex_controls.html

  4. 转:FORM:客制化Form的菜单栏和右鍵菜單

    Oracle EBS还允许客制化Form的菜单栏. 用户最多可以定义45个form-level的trigger,名称必须为SPECIALn, 其中SPECIAL1 to SPECIAL15属于Tool ...

  5. datetimepicker 初始化只显示年

    $("#overdue2").datetimepicker({ format: 'yyyy', autoclose: true, startView:4, minView:4, t ...

  6. Asp.Net MVC是否针对每次请求都重新创建一个控制器实例

    一.Asp.Net MVC是否针对每次请求都重新创建一个控制器实例 默认情况下,答案是确定的. ControllerBuilder类 ControllerBuilder.Current用户获取默认的控 ...

  7. ACM——3n+1

    3n+1 时间限制(普通/Java):1000MS/3000MS          运行内存限制:65536KByte总提交:937            测试通过:386 描述 对于任意大于1的自然 ...

  8. 【C#】获取本地Cookie的问题

    using System; using System.Net; using System.IO; using System.Text; // // TODO: 在此处添加代码以启动应用程序 // st ...

  9. NET环境下的未处理异常(unhandled exception)的解决方案

    NET环境下的未处理异常(unhandled exception )的解决方案 .Net 框架提供了非常强大的异常处理机制,同时对一些非托管代码很难控制的系统问题比如指针越界,内存泄漏等提供了很好的解 ...

  10. Ajax异步的回调函数执行了多遍

    问题: 在做下拉滚动加载时(类似于qq空间下拉加载),数据向下滚动一次,就会加载一次,即append一下,跟踪js后,发现回调函数执行了多次,导致append将上次的append结果append上了, ...