Uva 12361 File Retrieval 后缀数组+并查集
题意:有F个单词,1 <= F <=60 , 长度<=10^4, 每次可以输入一个字符串,所有包含该字串的单词会形成一个集合。
问最多能形成多少个不同的集合。集合不能为空。
分析:用后缀数组处理。然后首先考虑一个单词形成一个集合的情况,若该单词是其他单词的字串,则该单词显然不会形成一个集合,那么利用后缀数组,
对于每个单词看能否与其他单词有LCP,且LCP 长度为该单词本身长度。
然后就是多个单词形成集合的情况:比较简单的处理方式就是将h数组值相同的下标集中存储,比如h[x] = h[y] = h[z] = 5, 那么将x,y,z存到h
值对应为5的数组中,然后按照h值,假设为v,从大到小的顺序,将所有h值为v的下标与其周围的LCP大于v的(h[v-1],h[v])对应的子串,更新并查集。实际意义就是,每次将h值为h[v]的一些子串所在的单词合并到之前h值> h[v]的子串所在的单词形成的并查集中,得到的并查集中单词一定有长度>=h[v]公共字串,这样的并查集实际就是一个合法的单词集合,可以利用二进制表示,每次得到新的集合则将二进制表示加入到统计集合的set中,最后结果就是set的大小。
AC代码其实是比赛时写的,当时多个单词部分不是上面这种写法,不过类似。
#include <bits/stdc++.h>
#define in freopen("solve_in.txt", "r", stdin);
#define bug(x) printf("Line %d:>>>>>>>\n", (x)); #define REV(a) reverse((a).begin(), (a).end())
#define READ(a, n) {REP(i, n) cin>>(a)[i];}
#define REP(i, n) for(int i = 0; i < (n); i++)
#define VREP(i, n, base) for(int i = (n); i >= (base); i--)
#define Rep(i, base, n) for(int i = (base); i < (n); i++)
#define REPS(s, i) for(int i = 0; (s)[i]; i++)
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef map<ULL, int> UMps;
set<ULL> se; const int maxn = + ;
const int maxm = ;
const int maxlen = maxn*maxm+;
int s[maxlen];
int sa[maxlen], t[maxlen], t2[maxlen], c[maxlen], n, m, dp[maxlen][];
int num[maxlen];
LL ans;
void build_sa(int m) {
int *x = t, *y = t2; REP(i, m) c[i] = ;
REP(i, n) c[x[i] = s[i]]++;
Rep(i, , m) c[i] += c[i-];
VREP(i, n-, ) sa[--c[x[i]]] = i; for(int k = ; k <= n; k <<= ) {
int p = ; Rep(i, n-k, n) y[p++] = i;
REP(i, n) if(sa[i] >= k) y[p++] = sa[i]-k; REP(i, m) c[i] = ;
REP(i, n) c[x[y[i]]]++;
Rep(i, , m) c[i] += c[i-]; VREP(i, n-, ) sa[--c[x[y[i]]]] = y[i];
swap(x, y);
p = , x[sa[]] = ;
Rep(i, , n)
x[sa[i]] = y[sa[i-]] == y[sa[i]] && y[sa[i-]+k] == y[sa[i]+k] ? p- : p++;
if(p >= n) break;
m = p;
}
}
int rk[maxlen], h[maxlen]; void getHeight() {
int j, k = ;
h[] = ;
REP(i, n) rk[sa[i]] = i;
REP(i, n) {
if(k) k--;
if(rk[i] == )
continue;
j = sa[rk[i]-];
while( s[i+k] == s[j+k]) k++;
h[rk[i]] = k;
}
}
void RMQ_init() {
REP(i, n) dp[i][] = h[i];
for(int k = ; (<<k) <= n; k++)
for(int i = ; i + (<<k) <= n; i++)
dp[i][k] = min(dp[i][k-], dp[i+(<<(k-))][k-]);
}
int RMQ(int l, int r) {
int k = ;
while((<<(k+)) <= r-l+) k++;
return min(dp[l][k], dp[r-(<<k)+][k]);
}
char word[maxm][maxn];
int nn;
inline int idx(char ch) {
return ch-'a'+;
}
int vis[], slen[]; void solveSingle() {
se.clear();
memset(vis, , sizeof vis);
for(int i = ; i < n; i++){
if(h[i]){
if(num[sa[i]] != - && h[i] == slen[num[sa[i]]])
vis[num[sa[i]]] = ;
if(num[sa[i-]] != - && h[i] == slen[num[sa[i-]]])
vis[num[sa[i-]]] = ;
}
}
for(int i = ; i < nn; i++) if(!vis[i])
se.insert(1ULL<<i);
}
void dfs(int l, int r, int now) {
if(l >= r)
return;
ULL tmp; for(int i = l; i < r; ) {
tmp = ;
while(i < r && h[i] <= now)
i++;
if(i >= r)
break;
int mx = (int)1e9;
int j = i;
mx = min(mx, h[j]);
if(j < r && num[sa[j-]] != -)
tmp |= 1ULL<<num[sa[j-]];
while(j < r && h[j] > now) {
mx = min(mx, h[j]);
if(num[sa[j]] != -)
tmp |= 1ULL<<num[sa[j]];
j++;
}
if(tmp)
se.insert(tmp);
dfs(i, j, mx);
i = j;
}
}
void solve() {
build_sa();
getHeight();
solveSingle();
ULL tmp;
for(int i = ; i < n; ) {
int mx = (int)1e9;
tmp = ;
while(i < n && !h[i])
i++;
if(i >= n)
break;
mx = min(mx, h[i]);
int j = i;
if(j < n && num[sa[j-]] != -)
tmp |= 1ULL<<num[sa[j-]];
while(j < n && h[j]) {
mx = min(mx, h[j]);
if(num[sa[j]] != -)
tmp |= 1ULL<<num[sa[j]];
j++;
}
if(tmp)
se.insert(tmp);
dfs(i, j, mx);
i = j;
}
printf("%llu\n", (ULL)se.size());
}
int main() { while(scanf("%d", &nn), nn) {
n = ;
memset(num, -, sizeof num);
for(int i = ; i < nn; i++) {
slen[i] = ;
scanf("%s", word[i]);
for(int j = ; word[i][j]; j++) {
slen[i]++;
s[n] = idx(word[i][j]);
num[n++] = i;
}
s[n++] = +i;
}
s[n-] = ;
solve();
}
return ;
}
Uva 12361 File Retrieval 后缀数组+并查集的更多相关文章
- BZOJ 4566 JZYZOJ 1547 [haoi2016T5]找相同子串 后缀数组 并查集
http://172.20.6.3/Problem_Show.asp?id=1547 http://www.lydsy.com/JudgeOnline/problem.php?id=4566 单纯后缀 ...
- NOI 2015 品酒大会 (后缀数组+并查集)
题目大意:略 40分暴力还是很好写的,差分再跑个后缀和 和 后缀最大值就行了 一种正解是后缀数组+并查集 但据说还有后缀数组+单调栈的高端操作蒟蒻的我当然不会 后缀数组求出height,然后从大到小排 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )
求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ------------------------- ...
- 【学术篇】NOI2015 品酒大会 后缀数组+并查集
省选前大致是刷不了几道题了... 所以就找一些裸一点的题目练练板子算了= = 然而这题一点都不裸, 也并不怎么好写... 于是就浪费了将近一下午的时间... 然而还不是因为后缀数组板子不熟= = 首先 ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- 4199. [NOI2015]品酒大会【后缀数组+并查集】
Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加.在大会的晚餐上,调酒师 ...
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
[BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...
- loj6198谢特 后缀数组+并查集+Trie
先把问题放在后缀数组上考虑 已知两个数组a b,求min(a[i],...,a[j])+(b[i]^b[j])的最大值 套路题 初始每个点都是一个小连通块 把a按从大到小的顺序加入,计算当前加入边作为 ...
随机推荐
- JAXB - Annotations, Controlling Element Selection: XmlAccessorType, XmlTransient
If JAXB binds a class to XML, then, by default, all public members will be bound, i.e., public gette ...
- Appium Android 屏幕滑动
- java中内部类的定义与访问规则
java内部类总结 简单来说,内部类就是在我们所熟悉的类中的里面再定义一个类 为什么需要内部类? 当我们描述事物时,事物之中还有事物,我们就用内部类描述事物 因为内部事物在使用外部事物的内容 我举一个 ...
- C语言 宏/macor/#define/
C语言 宏/macor/#define 高级技巧 1.在进行调试的时候,需要进行打印/PRINT,可以通过define进行自定义.例如,自己最常用的DEBUG_PRINT() #define DEBU ...
- Wix: Show conditional message box
For example: Scenario: Show message box only during installation and MYPROPERTY has to be equal to & ...
- PHP学习笔记——上传文件到服务端的文件夹下
环境 开发包:appserv-win32-2.5.10 服务器:Apache2.2 数据库:phpMyAdmin 语言:php5,java 平台:windows 10 需求 编写一个PHP脚本页面,可 ...
- Web前端新人笔记之height、min-height的区别
浏览器参照基准:Firefox, Chrome, Safari, Opera, IE: * IE6不支持CSS min-height属性.最小高度的定义:1. 元素拥有默认高度:2. 当内容超出元素 ...
- 替换a链接的href和title
新项目准备验收,客户检测网页有安全隐患,说是当前网页使用“http://”有风险,指定外部链接不用“http://”怎么整…… 后来想到用JS替换字符串去操作,找了半天总算找到合用的,最终是用JQ去更 ...
- JS访问Struts 2 ValueStack中的内容
/* * var myArray = new Array("${vacant[0]}", "${vacant[1]}", "${vacant[2]}& ...
- MVC-ActionResult解说
HttpNotFoundResult: 专门用来响应Http404找不到网页的错误,在System.Web.Mvc.Controller类别中内建了一个HttpNotFound()方法,可以很方便的回 ...