SPOJ 220 Relevant Phrases of Annihilation(后缀数组)
You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages concerning the date of the planned attack on your island. You immedietaly send for the Bytelandian Cryptographer, but he is currently busy eating popcorn and claims that he may only decrypt the most important part of the text (since the rest would be a waste of his time). You decide to select the fragment of the text which the enemy has strongly emphasised, evidently regarding it as the most important. So, you are looking for a fragment of text which appears in all the messages disjointly at least twice. Since you are not overfond of the cryptographer, try to make this fragment as long as possible.
Input
The first line of input contains a single positive integer t<=10, the number of test cases. t test cases follow. Each test case begins with integer n (n<=10), the number of messages. The next n lines contain the messages, consisting only of between 2 and 10000 characters 'a'-'z', possibly with some additional trailing white space which should be ignored.
Output
For each test case output the length of longest string which appears disjointly at least twice in all of the messages.
题目大意:给n个字符串,求在每个字符串中出现至少两次且不重叠的最长子串的长度。
思路:每个字符串用不相同的字符连起来。求后缀数组和height[]数组。
二分长度L,检查长度。
检查的时候从前往后扫一遍,看有没有连起来的一部分,公共前缀大于等于L且在每个字符串中都出现了且不重叠。
复杂度为O(nlogn)
代码(0.34s):
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std; const int MAXN = ; char s[MAXN];
int id[MAXN];
int sa[MAXN], rank[MAXN], height[MAXN], c[MAXN], tmp[MAXN];
int n, m, T; void makesa(int m) {
memset(c, , m * sizeof(int));
for(int i = ; i < n; ++i) ++c[rank[i] = s[i]];
for(int i = ; i < m; ++i) c[i] += c[i - ];
for(int i = ; i < n; ++i) sa[--c[rank[i]]] = i;
for(int k = ; k < n; k <<= ) {
for(int i = ; i < n; ++i) {
int j = sa[i] - k;
if(j < ) j += n;
tmp[c[rank[j]]++] = j;
}
int j = c[] = sa[tmp[]] = ;
for(int i = ; i < n; ++i) {
if(rank[tmp[i]] != rank[tmp[i - ]] || rank[tmp[i] + k] != rank[tmp[i - ] + k])
c[++j] = i;
sa[tmp[i]] = j;
}
memcpy(rank, sa, n * sizeof(int));
memcpy(sa, tmp, n * sizeof(int));
}
} void calheight() {
for(int i = , k = ; i < n; height[rank[i++]] = k) {
k -= (k > );
int j = sa[rank[i] - ];
while(s[i + k] == s[j + k]) ++k;
}
} int mx[MAXN], mn[MAXN];
int stk[MAXN]; void update_max(int &a, int b) {
if(a == - || a < b) a = b;
} void update_min(int &a, int b) {
if(a == - || a > b) a = b;
} bool check(int L) {
int sum = , top = ;
memset(mx, -, m * sizeof(int));
memset(mn, -, m * sizeof(int));
memset(c, , m * sizeof(int));
for(int i = ; i < n; ++i) {
if(height[i] >= L) {
update_max(mx[id[sa[i]]], sa[i]);
update_min(mn[id[sa[i]]], sa[i]);
stk[++top] = id[sa[i]];
if(mx[id[sa[i]]] - mn[id[sa[i]]] >= L) {
if(!c[id[sa[i]]]) ++sum;
c[id[sa[i]]] = true;
if(sum >= m) return true;
}
} else {
sum = ;
while(top) {
int t = stk[top--];
mx[t] = mn[t] = -;
c[t] = false;
}
update_max(mx[id[sa[i]]], sa[i]);
update_min(mn[id[sa[i]]], sa[i]);
stk[++top] = id[sa[i]];
}
}
return false;
} int solve() {
int l = , r = ;
while(l < r) {
int mid = (l + r) >> ;
if(check(mid)) l = mid + ;
else r = mid;
}
return l - ;
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &m);
n = ;
for(int i = ; i < m; ++i) {
scanf("%s", s + n);
while(s[n]) id[n++] = i;
s[n++] = i + ;
}
s[n - ] = ;
makesa();
calheight();
printf("%d\n", solve());
}
}
SPOJ 220 Relevant Phrases of Annihilation(后缀数组)的更多相关文章
- SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串
题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags You ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
[题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
- SPOJ220 Relevant Phrases of Annihilation(后缀数组)
引用罗穗骞论文中的话: 先将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组.然后二分答案,再将后缀分组.判断的时候,要看是否有一组后缀在每个原来的字符串中至少出现两次,并 ...
- 【SPOJ 220】Relevant Phrases of Annihilation
http://www.spoj.com/problems/PHRASES/ 求出后缀数组然后二分. 因为有多组数据,所以倍增求后缀数组时要特判是否越界. 二分答案时的判断要注意优化! 时间复杂度\(O ...
- POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)
多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...
- SPOJ - PHRASES K - Relevant Phrases of Annihilation
K - Relevant Phrases of Annihilation 题目大意:给你 n 个串,问你最长的在每个字符串中出现两次且不重叠的子串的长度. 思路:二分长度,然后将height分块,看是 ...
- SPOJ - PHRASES Relevant Phrases of Annihilation (后缀数组)
You are the King of Byteland. Your agents have just intercepted a batch of encrypted enemy messages ...
- SPOJ PHRASES Relevant Phrases of Annihilation(后缀数组 + 二分)题解
题意: 给\(n\)个串,要你求出一个最长子串\(A\),\(A\)在每个字串至少都出现\(2\)次且不覆盖,问\(A\)最长长度是多少 思路: 后缀数组处理完之后,二分这个长度,可以\(O(n)\) ...
- 【SPOJ 220】 PHRASES - Relevant Phrases of Annihilation
[链接]h在这里写链接 [题意] 给你n(n<=10)个字符串. 每个字符串长度最大为1e4; 问你能不能找到一个子串. 使得这个子串,在每个字符串里面都不想交出 ...
随机推荐
- eclipse dbviewer,eclipse java8
进入/home/xxx(用户名)/.local/share/applications,看是否有eclipse和深度音乐desktop配置文件,为eclipse.desktop配置图标, 那现在终端输入 ...
- TEST指令
In the x86 assembly language, the TEST instruction performs a bitwise AND on two operands. The flags ...
- MyBatis3资料网址
官网: http://mybatis.github.io/mybatis-3/zh/index.html 资料: http://www.open-open.com/doc/list/112?o=d 整 ...
- 设计模式:命令模式(Command)
定 义:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排列或者记录请求日志,以及支持可撤销的操作. 结构图: Command类: abstract class Comma ...
- 自动换行的矢量文字(android demo)
由于矢量字体的宽度不同,自测android字体,发现当中文字体大小为100像素时,字母s等 宽度大概在52,字母l等 宽度大概在26,这样自动换行就不可以按字符的个数计算截取每行显示的字串. 直接上代 ...
- strcpy之代码的健壮性与可维护性
strcpy 函数的原型是: char * strcpy(char * strDest,const char * strSrc); 功能:把从strSrc地址开始且含有NULL结束符的字符串 ...
- Ubuntu 12.04+DarwinStreamingSrvr6.0.3 架设流媒体服务器
1.安装Ubuntu 12.04操作系统,网上很多教程.. 2.打开终端,下载darwin源代码DarwinStreamingSrvr6.0.3-Source.tar,补丁patch dss-6.0. ...
- imx6 RGB LCD
imx6dl需要支持lcd接口的屏,imx6dl的datasheet并没有明确的说明lcd相关的配置,只在Display Content Integrity Checker (DCIC)一章中介绍.本 ...
- 圆角边框_css控制形状
border-radius:500px 来让整个图像变成圆形. border-top-left-radius: 6px;(左上角圆角) border-top-right-radius: 6px;( ...
- 30天,O2O速成攻略【8.16武汉站】
活动概况 时间:2015年08月16日13:30-16:30 地点:光谷创业咖啡(光谷广场资本大厦一楼停车场内) 主办:APICloud.爱立示.MBA移动业务助理 网址:www.apicloud.c ...