2017 Multi-University Training Contest - Team 8 Fleet of the Eternal Throne
2017-08-23 19:59
429 查看
http://acm.hdu.edu.cn/showproblem.php?pid=6138
然后对于串x跑一遍自动机,把经过的点标记出来,表示这个点既是x的子串,又是某个串的前缀。因为每次用作标记的值都不一样,所以不用担心会记录错误。
再给串y跑一遍自动机,当经过标记的点时,更新一下答案即可,因为跑到标记的点的时候,这个点既是串x和串y的子串又是其他串的前缀,更新一下最大值即可。
题意:
给你n个串,q个查询,对于每次查询,输出串x和串y的最大公共子串的长度,而且这个子串是其他某些串的前缀,输出最长的长度。思路:
AC自动机,先对n个串建立一个AC自动机。字典树中每个节点维护一个到根的距离,相当于前缀的长度。然后对于串x跑一遍自动机,把经过的点标记出来,表示这个点既是x的子串,又是某个串的前缀。因为每次用作标记的值都不一样,所以不用担心会记录错误。
再给串y跑一遍自动机,当经过标记的点时,更新一下答案即可,因为跑到标记的点的时候,这个点既是串x和串y的子串又是其他串的前缀,更新一下最大值即可。
代码:
#include<bits/stdc++.h> using namespace std; struct Trie { int next[500010][26]; int fail[500010]; int end[500010]; int length[500010]; int root; int L; void init() { L = 0; root = newnode(); length[root] = 0; } int newnode() { for(int i = 0; i < 26; i++) { next[L][i] = -1; } end[L++] = 0; return L - 1; } void insert(char* buf) { int len = strlen(buf); int now = root; for(int i = 0; i < len; i++) { if(next[now][buf[i] - 'a'] == -1) { next[now][buf[i] - 'a'] = newnode(); } length[next[now][buf[i] - 'a']] = length[now] + 1; now = next[now][buf[i] - 'a']; } } void build() { queue<int> Q; fail[root] = root; for(int i = 0; i < 26; i++) { if(next[root][i] == -1) { next[root][i] = root; } else { fail[next[root][i]] = root; Q.push(next[root][i]); } } while(!Q.empty()) { int now = Q.front(); Q.pop(); for(int i = 0; i < 26; i++) { if(next[now][i] == -1) { next[now][i] = next[fail[now]][i]; } else { fail[next[now][i]] = next[fail[now]][i]; Q.push(next[now][i]); } } } } void update(char* buf,int vis){ int len = strlen(buf); int now = root; for(int i = 0; i < len; i++) { now = next[now][buf[i]-'a']; int temp = now; while(temp != root) { end[temp] = vis; temp = fail[temp]; } } } int query(char* buf,int vis) { int len = strlen(buf); int now = root; int res = 0; for(int i = 0; i < len; i++) { now = next[now][buf[i]-'a']; int temp = now; while(temp != root) { if(end[temp] == vis){ res = max(length[temp],res); } temp = fail[temp]; } } return res; } }; char buf[1000010]; int pos[10000010]; Trie ac; int main() { int T; int n; scanf("%d",&T); while(T--) { scanf("%d",&n); ac.init(); int d = 0; for(int i = 0; i < n; i++) { pos[i] = d; scanf("%s",buf + d); ac.insert(buf + d); d += strlen(buf + d) + 1; } ac.build(); int q; scanf("%d",&q); int vis = 1; int x,y; while(q--){ scanf("%d %d",&x,&y); x--; y--; ac.update(buf + pos[x],vis); printf("%d\n",ac.query(buf + pos[y],vis)); vis++; } } return 0; }
相关文章推荐
- 2017 Multi-University Training Contest - Team 8:Fleet of the Eternal Throne(AC自动机)
- HDU 6138 Fleet of the Eternal Throne(2017 Multi-University Training Contest 8)
- HDU 6138 Fleet of the Eternal Throne (后缀数组+字典树, 2017 Multi-Univ Training Contest 8)
- 2017 Multi-University Training Contest - Team 7:1003. Color the chessboard(...)
- 【模拟】2017 Multi-University Training Contest 1 The Battle of Chibi
- hdu 6051 If the starlight never fade [欧拉函数] [2017 Multi-University Training Contest - Team 2]
- 2017 Multi-University Training Contest - Team 3 1003(hdu 6058) Kanade's sum(链表)(set)
- 2017 Multi-University Training Contest - Team 3 - 1003
- hdu 6058 Kanade's sum(链表)(2017 Multi-University Training Contest - Team 3 )
- 2017 Multi-University Training Contest - Team 3
- HDU 6069 Counting Divisors(素数筛法+枚举+技巧)——2017 Multi-University Training Contest - Team 4
- 2017 Multi-University Training Contest - Team 3 & hdu6058、Kanade's sum
- hdu 6069 Counting Divisors(约数个数)(2017 Multi-University Training Contest - Team 4 )
- 2017 Multi-University Training Contest - Team 4 - 1003
- hdu 6070 Dirt Ratio(二分+线段树)(2017 Multi-University Training Contest - Team 4 )
- 2017 Multi-University Training Contest - Team 4-hdu 6071 Lazy Running
- hdu 6071 Lazy Running(优先队列+dijkstra)(2017 Multi-University Training Contest - Team 4)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- 2017 Multi-University Training Contest - Team 6:1010&hdu6105、Gameia
- 2017 Multi-University Training Contest - Team 4 Questionnaire