NEUOJ 720 (字典树+LCA || 二分+哈希)
来源:互联网 发布:mac vnc 编辑:程序博客网 时间:2024/06/12 20:21
题目链接:点击这里
Problem: 头哥的烦恼
Time limit: 5s Mem limit: 1000 MB AC/Submission: 16/94 Discuss
Problem Description
头哥,众所周知,作为acm队的主力选手,最近遇到了一些烦恼,那就是CET-4临近了,但是他还有很多单词没记住.
现在头哥有n个单词没记住,(所有的单词长度加起来不超过5e5),他需要区分其中的m对单词,因为两个单词前面有一部分是一样的,所以他只需要记住后面不相等的部分,所以头哥想要知道每对单词最长相等的前缀长度
Input
The first line of the input contains the number of test cases T.
Each test case begins with two integers n and m, indicate the number of words and queries.
Then n lines follow, each line contains a word (consist only of lowercase letters ‘a’-‘z’).
Then m lines follow, each line contains two integer u, v., meaning Brother want to query the word u and word v. (u may equal to v)
Output
For each test case, output one line containing “Case #x: ”, x means the case number (starting from 1).
Then next m lines, each line just print the answer of the query.
Sample Input
2
3 1
a
aa
aaa
1 3
3 2
ab
abc
bca
1 2
2 3
Sample Output
Case #1:
1
Case #2:
2
0
题意:求两个字符串的最长公共前缀长度.
把所有的字符串加入字典树,然后每次求两个字符串结尾节点的LCA深度就好了.
也可以处理好每一个字符串的哈希序列,然后直接在这个哈希序列上二分.
字典树+LCA
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#include <map>#include <queue>#include <string>#include <time.h>using namespace std;#define maxn 511111struct node { int next[26];}tree[maxn];int n, m, cnt, root;char a[maxn];struct E { int v, next;} edge[maxn<<4];int head[maxn], tot;//LCAint fa[maxn][22], deep[maxn];//节点i第2^j个祖先 深度int DEG;bool vis[maxn];void bfs (int root) { DEG = 20; queue <int> q; while (!q.empty ()) q.pop (); deep[root] = 0; fa[root][0] = root; q.push (root); memset (vis, 0, sizeof vis); vis[root] = 1; while (!q.empty ()) { int u = q.front (); q.pop (); for (int i = 1; i < DEG; i++) { fa[u][i] = fa[fa[u][i-1]][i-1]; } for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if (vis[v]) continue; deep[v] = deep[u]+1; fa[v][0] = u; q.push (v); vis[v] = 1; } }}int LCA (int u, int v) { if (deep[u] > deep[v]) swap (u, v); int hu = deep[u], hv = deep[v]; int tu = u, tv = v; for (int det = hv-hu, i = 0; det; det >>= 1, i++) if (det&1) { tv = fa[tv][i]; } if (tu == tv) return tu; for (int i = DEG-1; i >= 0; i--) { if (fa[tu][i] == fa[tv][i]) continue; tu = fa[tu][i]; tv = fa[tv][i]; } return fa[tu][0];}void add_edge (int u, int v) { edge[tot].v = v, edge[tot].next = head[u], head[u] = tot++;}void init () { tot = cnt = 0; memset (head, -1, sizeof head); root = 0; memset (tree[0].next, -1, sizeof tree[0].next);}//字典树int new_node () { ++cnt; memset (tree[cnt].next, -1, sizeof tree[cnt].next); return cnt;}int insert (char *a) { int len = strlen (a); int p = root; for (int i = 0; i < len; i++) { int id = a[i]-'a'; if (tree[p].next[id] == -1) { tree[p].next[id] = new_node (); add_edge (p, tree[p].next[id]); } p = tree[p].next[id]; } return p;}int pos[maxn];//每一个字符串的尾巴在字典树中对应的节点int main () { int t, kase = 0; scanf ("%d", &t); while (t--) { init (); scanf ("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf ("%s", a); pos[i] = insert (a); } bfs (0); //dfs (0, 0); printf ("Case #%d:\n", ++kase); while (m--) { int u, v; scanf ("%d%d", &u, &v); printf ("%d\n", deep[LCA (pos[u], pos[v])]); } } return 0;}
哈希+二分
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#include <map>#include <queue>#include <cstdlib>#include <string>using namespace std;#define ull unsigned long long#define seed 131#define maxn 511111vector <ull> a[maxn];int n, m;char str[maxn];ull f (char a) { return a-'a'+1;}int main () { int t, kase = 0; scanf ("%d", &t); while (t--) { scanf ("%d%d", &n, &m); printf ("Case #%d:\n", ++kase); for (int i = 1; i <= n; i++) { a[i].clear (); scanf ("%s", str); int len = strlen (str); ull hash = 0; for (int j = 0; j < len; j++) { hash = hash*seed + f(str[j]); a[i].push_back (hash); if (j) a[i][j] += a[i][j-1]; } } while (m--) { int u, v; scanf ("%d%d", &u, &v); if (a[u][0] != a[v][0]) { printf ("0\n"); continue; } int r = min (a[u].size (), a[v].size ())-1; int l = 0; while (r-l > 1) { int mid = (l+r)>>1; if (a[u][mid] == a[v][mid]) { l = mid; } else r = mid; } printf ("%d\n", (a[u][r] == a[v][r] ? r : l)+1); } } return 0;}
- NEUOJ 720 (字典树+LCA || 二分+哈希)
- NEUOJ 711 (字典树)
- NEUOJ 719 (字典树 字典序)
- hdu4757(LCA+可持久化字典树)
- POJ 2503 Babelfish(STL、二分、字典树、哈希)
- NEUOJ 720 头哥的烦恼
- NEUOJ 1393 Some Numbers(线段树)
- hdu 4757 Tree 可持续化01字典树+lca
- hdu 3830 二分+LCA
- bzoj2144 LCA+二分
- [BZOJ3572][Hnoi2014]世界树(虚树+树形dp+二分+lca)
- poj2503-字典树&&二分查找&&快速排序
- 2503 Babelfish 二分 字典树 map容器
- UVA 12124 Assemble (二分 + 字典树)
- HDU--3830[Checkers] LCA+二分
- 【bzoj2145】【跳跳棋】【二分+lca】
- HDU 3830 - Checkers(二分LCA)****
- bzoj2144 跳跳棋 二分+lca
- 学习笔记(九)MFC修改屏幕分辨率
- java方法重写和重载
- 使用Python进行简单的图像处理
- viewpager滑动时下面的圆点跟着滑动的代码实现
- 为什么在12306买火车票要装根证书?
- NEUOJ 720 (字典树+LCA || 二分+哈希)
- MFC中设置静态文本框的时间
- MFC总结之CListCtrl用法及技巧
- windows 下 mysql 导入 大文本数据
- ckeditor和ckfinder配置上传图片
- URL常用操作总结
- 缓存原理
- MySQL索引原理及慢查询优化
- Android studio中Build.gradle详细配置说明