后缀平衡树 nbut1653 String in the tree
来源:互联网 发布:office包含哪些软件 编辑:程序博客网 时间:2024/06/09 21:18
传送门:点击打开链接
题意:告诉你一棵树,每个节点有一个字母,然后要求分别输出每个节点到根节点这条路径上的不重复的子串个数。
思路:因为是树形结构,我们就没办法用后缀数组搞了,必须要想办法能动态维护就好啦
我们这里用后缀平衡树来做到动态维护SA
首先我们要明确这道题的思路,每增加一个节点,根据后缀数组的知识我们知道,会多增加l-max(H[i],H[i+1])个子串,H表示高度数组,也就是两个相邻的SA的最长前缀
问题就出来了,我们如何来动态维护SA
我们用一个set来搞,set相当于一颗平衡树,里面是按照SA排序好的,现在我们来增加一个节点,我们要在字符串的前面增加这个节点,这样就相当于后缀都不变,我又多增加了一条串,因为现在set里面是有序的,所以我只要能做到比较后缀的字典序大小关系,我就能够快速把它插入到set中去。
比较后缀的字典序大小,我们用经典的二分+hash求lcp的方法来搞定
不得不说字符串hash如果都用unsigned long long来存的话还真方便,减法乘法啥的都不需要取模~
#include<map>#include<set>#include<cmath>#include<ctime>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iomanip>#include<iostream>#include<algorithm>#include<functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;typedef pair<int, int>PII;const int MX = 2e4 + 5;const int mod = 1e9 + 7;const int INF = 0x3f3f3f3f;const int seed = 131;typedef unsigned long long ULL;struct Edge { int v, nxt;} E[MX];int Head[MX], rear;void edge_init() { rear = 0; memset(Head, -1, sizeof(Head));}void edge_add(int u, int v) { E[rear].v = v; E[rear].nxt = Head[u]; Head[u] = rear++;}int n;char S[MX];ULL Hash[MX], F[MX];LL ans[MX];bool check(int u, int v, int m) { ULL h1 = Hash[u] - Hash[u - m] * F[m]; ULL h2 = Hash[v] - Hash[v - m] * F[m]; return h1 == h2;}int lcp(int u, int v) { int l = 0, r = min(u, v), m; while(l <= r) { m = (l + r) >> 1; if(check(u, v, m)) l = m + 1; else r = m - 1; } return l - 1;}struct cmp { bool operator()(const int &a, const int &b) { int p = lcp(a, b); if(a == p && b != p) return true; if(b == p && a != p) return false; int u = Hash[a - p] - Hash[a - p - 1] * seed; int v = Hash[b - p] - Hash[b - p - 1] * seed; return u < v; }};set<int, cmp>W;void DFS(int u, int f, int l, LL s, ULL h) { h = h * seed + S[u]; Hash[l] = h; set<int, cmp>::iterator e = W.insert(l).first, e1 = e, e2 = e; int Max = 0; if(e1 != W.begin()) e1--, Max = max(Max, lcp(l, *e1)); if(++e2 != W.end()) Max = max(Max, lcp(l, *e2)); s += l - Max; ans[u] = s; for(int i = Head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if(v == f) continue; DFS(v, u, l + 1, s, h); } W.erase(l);}int main() { F[0] = 1; //FIN; for(int i = 1; i < MX; i++) { F[i] = F[i - 1] * seed; } int T; scanf("%d", &T); while(T--) { W.clear(); edge_init(); scanf("%d", &n); for(int i = 1; i <= n - 1; i++) { int u, v; scanf("%d%d", &u, &v); edge_add(u, v); edge_add(v, u); } scanf("%s", S + 1); DFS(1, -1, 1, 0, 0); for(int i = 1; i <= n; i++) { printf("%I64d\n", ans[i]); } } return 0;}
0 0
- 后缀平衡树 nbut1653 String in the tree
- 后缀平衡树
- 后缀平衡树
- UOJ35 后缀排序[后缀平衡树]
- 后缀平衡树 bzoj3682 Phorni
- 后缀平衡树学习笔记
- [bzoj2555][后缀平衡树]SubString
- [后缀平衡树][JZOJ4384]hashit
- 后缀树【Suffix Tree】
- Suffix Tree 后缀树
- AVL Tree 平衡二叉树
- 平衡二叉树(AVL Tree)
- Avl - tree 平衡二叉树
- AVL Tree(平衡二叉树)
- 平衡树 || Red-Black Tree
- AVL Tree平衡二叉树
- 后缀树(suffix Tree)和后缀数组
- 平衡树 balanced binary tree (AVL tree)
- 从初识Linux到离不开系列(四)循序渐进
- Android Studio API23以后HttpClient
- NYOJ-组合数
- ATL与COM之间的关系、ATL的特点与基本使用方法
- Android TV Studuy1-2
- 后缀平衡树 nbut1653 String in the tree
- 需要经常看的故事
- c++ string 用法总结
- 51 nod 1130 N的阶乘的长度 V2(斯特林近似)
- hdu--2089(打表)
- tomcat-闪退和启动两个tomcat解决方法
- Oracle Restart可以用来给Oracle GoldenGate 做 High Availability 使用么?
- Android Wear开启通过蓝牙调试后,显示"主机:已断开连接"解决方法
- Notepad++直接编译运行Java