hdu 5790 Prefix (字典树 + 主席树)
2016-08-10 19:04
218 查看
Prefix
Time Limit: 2000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 519 Accepted Submission(s): 157
Problem Description
Alice gets N strings. Now she has Q questions to ask you. For each question, she wanna know how many different prefix strings between Lth and Rth strings. It's so easy right? So solve it!
Input
The input contains multiple test cases.
For each test case, the first line contains one integer N(1≤N≤100000).
Then next N lines contain N strings and the total length of N strings is between 1 and 100000. The next line contains one integer Q(1≤Q≤100000).
We define a specail integer Z=0. For each query, you get two integer L, R(0=<L,R<N). Then the query interval [L,R] is [min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]. And Z change to the answer of this query.
Output
For each question, output the answer.
Sample Input
3
abc
aba
baa
3
0 2
0 1
1 1
Sample Output
7
6
3
题目的意思是 求第 f(l) 到 f(r) 的区间的字符串的不同前缀 ( f(x)在题目中给出 )字符串的总长度不会超过 100000
思路 因为 f (x) 是一个包含z的函数 而 z 是基于每次给出的答案 (初始的z 是 0) 所以强制在线
题目说 所以建一棵字典树 节点保存最后出现的字符串的编号
在建树的时候 把每个字符串走过的节点的数据存进另一个数组arr 并更新这个节点
可以再开个数组 nb 保存一下每个字符串添加进去 字典树的节点数 (1 ~ i 的前缀数)
然后我们可以 得出 ANS = nb[r] - nb[l-1] + ( arr[l 的首字符位置 ] ~~ arr[r 尾字符] 中比 l 小的个数 )
统计 比l 小的个数的 用主席树维护
昨天TLE到- - 于是今天看了下主席树的讲解 也不知道这个 嗯 算不算正常的主席树
#include<iostream> #include<algorithm> #include<cstdlib> #include<cctype> #include<cstdio> #include<string> #include<cstring> #include<vector> #include<set> #include<map> #include<queue> #include<cmath> #include<bitset> #define pi acos(-1.0) #define inf 1<<29 #define INF 0x3f3f3f3f #define zero 1e-8 const int li[] = { -1, 0, 1, 0}; const int lj[] = {0, -1, 0, 1}; using namespace std; const int N = 100007 + 107; struct node { int next[27]; int cnt; } tree ; int fin, least; struct lo { int l, r, data; lo(){l=r=data=0;} void show() { cout << "l: " << l << " r: " << r << " data: " << data << endl; } } cmtree[N * 21]; int root ; int pt; int sum; int nb , arr[21*N], lef , arrnum; char str ; int tot, treenum; int cnt; void init() { arrnum = treenum = 0; memset(tree,0,sizeof(tree)); memset(cmtree,0,sizeof(cmtree)); sum=pt = 0; } void build(int i, int num, int id) { if (str[i] == '\0') return; if (!tree[num].next[str[i] - 'a']) { tree[num].next[str[i] - 'a'] = (++treenum); arr[++arrnum] = id; } else { arr[++arrnum] = tree[tree[num].next[str[i] - 'a']].cnt; } tree[tree[num].next[str[i] - 'a']].cnt = id; build(i + 1, tree[num].next[str[i] - 'a'], id); } void show() { for (int i = 0; i < 17; ++i) cout << "i: " << i << " arr: " << arr[i] << " lef" << lef[i] << " nb" << nb[i] << endl; } void build(int from, int node, int left, int right, int arrow) { ++pt; int now = pt; if (arrow == 1) cmtree[from].l = pt; else cmtree[from].r = pt; if (left == right) { cmtree[pt].l = cmtree[pt].r = -1; cmtree[pt].data = 0; return; } build(now, node * 2, left, (left + right) / 2, 1); build(now, node * 2 + 1, (left + right) / 2 + 1, right, 2); return; } void update(int node, int left, int right, int from, int mod, int data, int arrow) { ++pt; int now = pt; if (arrow == 1) cmtree[from].l = pt; else cmtree[from].r = pt; int mid = (left + right) / 2; if (left == right) { cmtree[pt].data = cmtree[mod].data + 1; cmtree[pt].l = cmtree[pt].r = -1; return; } if (data <= mid) { update(node * 2, left, mid, pt, cmtree[mod].l, data, 1); cmtree[now].r = cmtree[mod].r; } else { update(node * 2 + 1, mid + 1, right, pt, cmtree[mod].r, data, 2); cmtree[now].l = cmtree[mod].l; } cmtree[now].data = cmtree[cmtree[now].l].data + cmtree[cmtree[now].r].data; } void query(int node, int left, int right, int Begin, int End, int next) { if (left > End || right < Begin) return ; if (left >= Begin && right <= End) { sum += cmtree[next].data; return; } int mid = (left + right) / 2; query(node * 2, left, mid, Begin, End, cmtree[next].l); query(node * 2 + 1, mid + 1, right, Begin, End, cmtree[next].r); } int main() { int n; while (~scanf("%d", &n)) { init(); for (int i = 1; i <= n; ++i) { scanf("%s", str); lef[i] = arrnum + 1; build(0, 0, i); nb[i] = treenum; } lef[n + 1] = arrnum + 1; pt = 0; root[0] = pt; build(root[0], 1, 1, n, 1); for (int i = 1; i <= arrnum; ++i) { root[i] = ++pt; update(1, 1, n, root[i], root[i - 1] + 1, arr[i], 1); } int m; scanf("%d", &m); int z = 0; for (int i = 0; i < m; ++i) { int l, r; scanf("%d %d", &l, &r); l = (z + l) % n + 1; r = (z + r) % n + 1; if(l > r) swap(l, r); sum = fin = 0; if (l > 1) { query(1, 1, n, 1, l - 1, root[lef[r+1]-1] + 1); int ans1 = sum; sum = 0; query(1, 1, n, 1, l - 1, root[lef[l]-1] + 1); int ans2 = sum; fin = ans1 - ans2; } z = nb[r] - nb[l - 1] + fin; printf("%d\n", z); } } return 0; }
相关文章推荐
- HDU 5790 Prefix(字典树、主席树)
- hdu 5790 Prefix(字典树+主席树)
- hdu 5790 Prefix(trie+主席树,好题)
- 2016多校第五场 1010 HDU 5790 Prefix 主席树
- hdu 5790 prefix 主席树在线维护区间不同数的个数
- hdu5790 Prefix(2016多校第五场1009)trie+主席树
- hdu 5790 prefix 主席树
- [HDU 5790] Prefix (字符串hash+主席树)
- hdu_5790_Prefix(trie+主席树)
- 【HDU - 5790 】Prefix(主席树+Trie树)
- HDU5790 Prefix 字典树+主席树
- Hdu 5790 Prefix(每次查询问你第L个字符串和第R个字符串之间的公共前缀有多少个)
- 【HUD-5790】Prefix (主席树+tire)
- HDU-5790 Tire树+主席树
- hdu 1251 统计难题 字典树
- HDU 3172 Virtual Friends // 并查集,字典树
- hdu 4348 To the moon (主席树区间更新)
- hdu 1671 Phone List (字典树)
- 2017 icpc广西邀请赛 K.Query on A Tree (hdu 6191)可持久化字典树
- HDU 1251(搜索题,典型的字典树问题)