SPOJ PHRASES 后缀数组
题目链接:http://www.spoj.com/problems/PHRASES/en/
题意:给定n个字符串,求一个最长的子串至少在每个串中的不重叠出现次数都不小于2。输出满足条件的最长子串长度
思路:根据<<后缀数组——处理字符串的有力工具>>的思路,先将 n个字符串连起来, 中间用不相同的且没有出现在字符串中的字符隔开, 求后缀数组。 然后二分答案, 再将后缀分组。判断的时候, 要看是否有一组后缀在每个原来的字符串中至少出现两次, 并且在每个原来的字符串中, 后缀的起始位置的最大值与最小值之差是否不小于当前答案(判断能否做到不重叠, 如果題目中没有不重叠的要求, 那么不用做此判断) 。这个做法的时间复杂度为 0(nlogn) 。
#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<time.h>
#include<cmath>
#include<set>
using namespace std;
typedef long long int LL;
const int MAXN = * * ;
int wa[MAXN], wb[MAXN], wv[MAXN], WS[MAXN];
int cmp(int *r, int a, int b, int l)
{
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int *r, int *sa, int n, int m)
{
int i, j, p, *x = wa, *y = wb, *t;
for (i = ; i < m; i++) WS[i] = ;
for (i = ; i < n; i++) WS[x[i] = r[i]]++;
for (i = ; i < m; i++) WS[i] += WS[i - ];
for (i = n - ; i >= ; i--) sa[--WS[x[i]]] = i;
for (j = , p = ; p < n; j *= , m = p)
{
for (p = , i = n - j; i < n; i++) y[p++] = i;
for (i = ; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = ; i < n; i++) wv[i] = x[y[i]];
for (i = ; i < m; i++) WS[i] = ;
for (i = ; i < n; i++) WS[wv[i]]++;
for (i = ; i < m; i++) WS[i] += WS[i - ];
for (i = n - ; i >= ; i--) sa[--WS[wv[i]]] = y[i];
for (t = x, x = y, y = t, p = , x[sa[]] = , i = ; i < n; i++)
x[sa[i]] = cmp(y, sa[i - ], sa[i], j) ? p - : p++;
}
return;
}
int Rank[MAXN], height[MAXN], sa[MAXN];
void calheight(int *r, int *sa, int n){
int i, j, k = ;
for (i = ; i <= n; i++) { Rank[sa[i]] = i; }
for (i = ; i < n; height[Rank[i++]] = k){
for (k ? k-- : , j = sa[Rank[i] - ]; r[i + k] == r[j + k]; k++);
}
return;
}
int r[MAXN], len, n, t, Index[MAXN],vis[MAXN];
char sub[+];
struct Node{
int cnt,maxsa, minsa;
void init(){cnt = , maxsa = -, minsa = MAXN;}
}node[];
bool check(int x){
int tot = ,idx,Lidx;
for (int i = ; i <= n; i++){
node[i].init();
}
memset(vis, , sizeof(vis));
for (int i = ; i < len; i++){
//heigth[i]是sa[i]和sa[i-1]的LCP
idx = Index[sa[i]], Lidx = Index[sa[i - ]];
if (i == len - ){
for (int k = ; k <= n; k++){
//判断每个字符串的出现次数和后缀的起始位置的最大值和最小值的差是否不小于x
if (node[k].cnt >= && node[k].maxsa - node[k].minsa >= x){
tot++;
}
node[k].init();
}
if (tot == n){ return true; }//n个串都满足要求,说明长度x存在
tot = ;
break;
}
if (height[i] >= x){
if (!vis[i]){//每个后缀只算一次
vis[i] = ; node[idx].cnt++; //记录后缀在该组出现的次数
node[idx].maxsa = max(node[idx].maxsa, sa[i]);//最大值
node[idx].minsa = min(node[idx].minsa, sa[i]);//最小值
}
if (!vis[i-]){
vis[i - ] = ; node[Lidx].cnt++;
node[Lidx].maxsa = max(node[Lidx].maxsa, sa[i-]);
node[Lidx].minsa = min(node[Lidx].minsa, sa[i-]);
}
}
else{
for (int k = ; k <= n; k++){
//判断每个字符串的出现次数和后缀的起始位置的最大值和最小值的差是否不小于x
if (node[k].cnt >= &&node[k].maxsa-node[k].minsa>=x){
tot++;
}
node[k].init();
}
if (tot == n){ return true;} //n个串都满足要求,说明长度x存在
tot = ;
}
}
return false;
}
void solve(){
int L = , R = /, mid, ans = ;
while (R >= L){
mid = (L + R) / ;
if (check(mid)){
ans = mid;
L = mid + ;
}
else{
R = mid - ;
}
}
printf("%d\n", ans);
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
scanf("%d", &t);
while (t--){
scanf("%d", &n); len = ;
for (int i = , val = ; i <= n; i++, val++){
scanf("%s", &sub);
for (int j = ; j < strlen(sub); j++){
Index[len] = i; //记录每个拼接后每个位置属于原输入的哪个
r[len++] = (sub[j] - 'a' + n + );
}
Index[len] = i;
r[len++] = val;
}
da(r, sa, len, );
calheight(r, sa, len - );
solve();
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}
SPOJ PHRASES 后缀数组的更多相关文章
- SPOJ REPEATS 后缀数组
题目链接:http://www.spoj.com/problems/REPEATS/en/ 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现 ...
- SPOJ SUBST1 后缀数组
题目链接:http://www.spoj.com/problems/SUBST1/en/ 题意:给定一个字符串,求不相同的子串个数. 思路:直接根据09年oi论文<<后缀数组——出来字符串 ...
- SPOJ DISUBSTR 后缀数组
题目链接:http://www.spoj.com/problems/DISUBSTR/en/ 题意:给定一个字符串,求不相同的子串个数. 思路:直接根据09年oi论文<<后缀数组——出来字 ...
- Spoj-DISUBSTR - Distinct Substrings~New Distinct Substrings SPOJ - SUBST1~(后缀数组求解子串个数)
Spoj-DISUBSTR - Distinct Substrings New Distinct Substrings SPOJ - SUBST1 我是根据kuangbin的后缀数组专题来的 这两题题 ...
- SPOJ DISUBSTR ——后缀数组
[题目分析] 后缀数组模板题. 由于height数组存在RMQ的性质. 那么对于一个后缀,与前面相同的串总共有h[i]+sa[i]个.然后求和即可. [代码](模板来自Claris,这个板子太漂亮了) ...
- [spoj DISUBSTR]后缀数组统计不同子串个数
题目链接:https://vjudge.net/contest/70655#problem/C 后缀数组的又一神奇应用.不同子串的个数,实际上就是所有后缀的不同前缀的个数. 考虑所有的后缀按照rank ...
- Distinct Substrings SPOJ - DISUBSTR 后缀数组
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- SPOJ 694 (后缀数组) Distinct Substrings
将所有后缀按照字典序排序后,每新加进来一个后缀,它将产生n - sa[i]个前缀.这里和小罗论文里边有点不太一样. height[i]为和字典序前一个的LCP,所以还要减去,最终累计n - sa[i] ...
- spoj 694(后缀数组)
题意:求一个字符串的不重复子串的个数. 分析:对于下标为i的位置,能够产生的前缀子串个数为len-i(下标从0开始),对于与它字典序相邻的后缀产生的子串是重复的(就是他们的最长公共前缀),所以我们要减 ...
随机推荐
- yii验证码不使用model在控制器中进行验证
控制器 public function actionCheckLogin(){ if(!$this->createAction('verify_code')->validate($_POS ...
- rabbitmq_hearbeat
heartbeat[心跳检测],用于报告客户端与服务器之间连接的一种检测机制.在rabbitmq中有Sender和consumer. 为了确保rabbitmq与客户端的状态,需启用heartbeat. ...
- 环信SDK集成
利用环信SDK可以实现即时通讯,但在集成的过程中碰到了不少的坑. 注意 选择项目路径,这里以最新版环信demo为例 注意:环信的ChatDemoUI这个demo里边因为研发的同事为了照顾老版本的And ...
- 与你相遇好幸运,Waterline的多表关联
>一对一关联 表示一个模型可能只与另一个模型关联.为了使模型知道它与其他哪些模型关联,外键必需包含在记录中.. http://imfly.github.io/sails-docs/concept ...
- ASP.NET 客户端静态文件请求设置缓存(Client Cache)
通常在服务器端大家都已经做了很多缓存的工作,ASP.NET CACHE也好MemeryCache也好却总是忽略了客户端缓存. 因为大家都知道不管哪个client都会缓存已经访问过的站点,但是浏览器缓存 ...
- poj 1005:I Think I Need a Houseboat(水题,模拟)
I Think I Need a Houseboat Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 85149 Acce ...
- windows操作技巧
-------------------win7专有------------------- WIN+上下左右可以将当前窗口 最大化.左侧放置.右侧放置.最小化 WIN+Shift+左右是让窗口在多个屏幕 ...
- Oracle【IT实验室】数据库备份与恢复之三:OS备份/用户管理的备份与恢复
用户管理的备份与恢复也称 OS物理备份,是指通过数据库命令设置数据库为备份 状态,然后用操作系统命令,拷贝需要备份或恢复的文件.这种备份与恢复需要用户的 参与手工或自动完成. 对于使用 OS拷贝备份的 ...
- android 入门- 词汇
final Resources.Theme theme = context.getTheme(); TypedArray a = theme.obtainStyledAttributes();获得自定 ...
- centos6.4下安装php的imagick和imagemagick扩展教程
imagick在centos6.4的安装方法: .安装ImageMagick 代码如下: wget http://soft.vpser.net/web/imagemagick/ImageMagick- ...