【BZOJ 2746】旅行问题

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。 

 
分析:
  要求找出两个字符串的公共后缀满足这个后缀又是某一个字符串的前缀。
  用AC自动机解决,根据Fail指针的性质(指向最长的一个后缀满足它是某一个串的前缀)作LCA就好了。
 
代码:
  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 #ifdef Lightning
  5 #define NOTHING() printf ("\033[0m")
  6 #define RED() printf ("\033[31m")
  7 #define PURPLE() printf ("\033[35m")
  8 #define BLUE() printf ("\033[34m")
  9 #define GREEN() printf ("\033[32m")
 10 #endif
 11 
 12 struct Trie
 13 {
 14     long long key;
 15     int next[27], fail, frmq[23], fd;
 16 } trie[1000010];
 17 
 18 int n, m;
 19 int sta[1000010], city[2000010], num;
 20 int len, prev, size, now;
 21 int p1, p2, p3, p4;
 22 int que[1000010], head, rear;
 23 char str[1000010];
 24 
 25 inline int new_node (int ch, int father)
 26 {
 27     size++;
 28     trie[father].next[ch] = size;
 29     trie[size].key = (trie[father].key * 26 + ch) % 1000000007;
 30     return size;
 31 }
 32 
 33 void bfs ()
 34 {
 35     int node;
 36     for (que[head = rear = 0] = 0; head <= rear; head++)
 37     {
 38         node = que[head];
 39         for (int i = 0; i < 26; i++)
 40         {
 41             if (node) trie[node].fd = trie[trie[node].fail].fd + 1;
 42             else trie[node].fd = 0;
 43             if (trie[node].next[i])
 44             {
 45                 if (node) trie[trie[node].next[i]].fail = trie[trie[node].fail].next[i];
 46                 que[++rear] = trie[node].next[i];
 47             }else trie[node].next[i] = trie[trie[node].fail].next[i];
 48         }
 49     }
 50 }
 51 
 52 void frmq_build ()
 53 {
 54     for (int i = 1; i <= size; i++)
 55         trie[i].frmq[0] = trie[i].fail;
 56     for (int k = 0; k < 22; k++)
 57         for (int i = 1; i <= size; i++)
 58             trie[i].frmq[k + 1] = trie[trie[i].frmq[k]].frmq[k];
 59 }
 60 
 61 int lca (int e1, int e2)
 62 {
 63     if (trie[e1].fd > trie[e2].fd)
 64         e1 ^= e2, e2 ^= e1, e1 ^= e2;
 65     #ifdef Lightning
 66         GREEN ();
 67         printf ("DEPTH : %d %d\n", trie[e1].fd, trie[e2].fd);
 68         NOTHING ();
 69     #endif
 70     for (int i = 22; i >= 0; i--)
 71         if (trie[trie[e2].frmq[i]].fd >= trie[e1].fd)
 72             e2 = trie[e2].frmq[i];
 73     if (e1 == e2) return e1;
 74     #ifdef Lightning
 75         if (trie[e1].fd != trie[e2].fd)
 76         {
 77             RED ();
 78             printf ("\nWrong!!!\n");
 79             printf ("%d %d\n\n", trie[e1].fd, trie[e2].fd);
 80             NOTHING ();
 81         }
 82     #endif
 83     for (int i = 22; i >= 0; i--)
 84         if (trie[e1].frmq[i] != trie[e2].frmq[i])
 85             e1 = trie[e1].frmq[i], e2 = trie[e2].frmq[i];
 86     return trie[e1].frmq[0];
 87 }
 88 
 89 int main ()
 90 {
 91     #ifdef Lightning
 92         BLUE ();
 93         printf ("How many descriptions?\n - ");
 94         NOTHING ();
 95     #endif
 96     scanf ("%d", &n);
 97     size = 0;
 98     for (int i = 1; i <= n; i++)
 99     {
100         #ifdef Lightning
101             BLUE ();
102             printf ("Description %d - ", i);
103             NOTHING ();
104         #endif
105         scanf ("%s", str);
106         len = strlen (str);
107         prev = 0;
108         sta[i] = num;
109         #ifdef Lightning
110             BLUE ();
111             printf ("Index : %d   Start : %d\n", i, sta[i]);
112             NOTHING ();
113         #endif
114         for (int j = 0; j < len; j++)
115         {
116             now = trie[prev].next[str[j] - 'a'];
117             if (!now) now = new_node (str[j] - 'a', prev);
118             num++;
119             city[num] = prev = now;
120         }
121     }
122     #ifdef Lightning
123         GREEN ();
124         printf ("Checking...\nThe Size : %d\n", size);
125         printf ("Aho-Corasick Automation Building...\n");
126     #endif
127     bfs ();
128     #ifdef Lightning
129         printf ("Done...\n");
130         printf ("RMQ Building...\n");
131     #endif
132     frmq_build ();
133     #ifdef Lightning
134         BLUE ();
135         printf ("How many couples are there?\n - ");
136         NOTHING ();
137     #endif
138     scanf ("%d", &m);
139     for (int i = 1, node = 0; i <= m; i++)
140     {
141         #ifdef Lightning
142             BLUE ();
143             printf ("Couple %d - ", i);
144             NOTHING ();
145         #endif
146         scanf ("%d %d %d %d", &p1, &p2, &p3, &p4);
147         #ifdef Lightning
148             BLUE ();
149             printf ("Input : %d %d %d %d\n", p1, p2, p3, p4);
150             GREEN ();
151             printf ("Working...\n");
152             NOTHING ();
153         #endif
154         #ifdef Lightning
155             BLUE ();
156             printf ("City 1 : %d   City 2 : %d\n", sta[p1] + p2, sta[p3] + p4);
157             NOTHING ();
158         #endif
159         node = lca (city[sta[p1] + p2], city[sta[p3] + p4]);
160         #ifdef Lightning
161             GREEN ();
162             printf ("The LCA : %d      ", node);
163             printf ("The Answer : ");
164             NOTHING ();
165         #endif
166         printf ("%lld\n", trie[node].key);
167     }
168 }

PS:调试信息什么的不用管。。。

posted @ 2015-04-22 19:53  Lightning34  阅读(318)  评论(0编辑  收藏  举报