【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
aabb babb
2
1 3 2 3
1 4 2 4
Sample Output
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。
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:调试信息什么的不用管。。。