[POJ1226]Substrings(后缀数组)
给定 n 个字符串,求出现或反转后出现在每个字符串中的最长子串。
算法分析:
这题不同的地方在于要判断是否在反转后的字符串中出现。其实这并没有加大题目的难度。
只需要先将每个字符串都反过来写一遍,中间用一个互不相同的且没有出现在字符串中的字符隔开,
再将 n 个字符串全部连起来,中间也是用一个互不相同的且没有出现在字符串中的字符隔开,求后缀数组。
然后二分答案,再将后缀分组。
判断的时候,要看是否有一组后缀在每个原来的字符串或反转后的字符串中出现。
这个做法的时间复杂度为 O(nlogn)。
——代码
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 21001 int len, n, m, max_num, T;
int buc[N], x[N], y[N], sa[N], rank[N], height[N], belong[N], s[N];
char a[N];
bool f[]; inline void build_sa()
{
int i, k, p;
for(i = ; i < m; i++) buc[i] = ;
for(i = ; i < len; i++) buc[x[i] = s[i]]++;
for(i = ; i < m; i++) buc[i] += buc[i - ];
for(i = len - ; i >= ; i--) sa[--buc[x[i]]] = i;
for(k = ; k <= len; k <<= )
{
p = ;
for(i = len - ; i >= len - k; i--) y[p++] = i;
for(i = ; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
for(i = ; i < m; i++) buc[i] = ;
for(i = ; i < len; i++) buc[x[y[i]]]++;
for(i = ; i < m; i++) buc[i] += buc[i - ];
for(i = len - ; i >= ; i--) sa[--buc[x[y[i]]]] = y[i];
std::swap(x, y);
p = , x[sa[]] = ;
for(i = ; i < len; i++)
x[sa[i]] = y[sa[i - ]] == y[sa[i]] && y[sa[i - ] + k] == y[sa[i] + k] ? p - : p++;
if(p >= len) break;
m = p;
}
} inline void build_height()
{
int i, j, k = ;
for(i = ; i < len; i++) rank[sa[i]] = i;
for(i = ; i < len; i++)
{
if(!rank[i]) continue;
if(k) k--;
j = sa[rank[i] - ];
while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++;
height[rank[i]] = k;
}
} inline bool check(int k)
{
int i, cnt = ;
memset(f, , sizeof(f));
f[belong[sa[]]] = ;
for(i = ; i < len; i++)
if(height[i] >= k && !f[belong[sa[i]]])
{
cnt++;
f[belong[sa[i]]] = ;
if(cnt == n) return ;
}
else if(height[i] < k)
{
cnt = ;
memset(f, , sizeof(f));
f[belong[sa[i]]] = ;
}
return ;
} inline int solve()
{
int l = , r = len, ans = , mid;
while(l <= r)
{
mid = (l + r) >> ;
if(check(mid)) ans = mid, l = mid + ;
else r = mid - ;
}
return ans;
} int main()
{
int i, j, l;
scanf("%d", &T);
while(T--)
{
len = ;
m = ;
scanf("%d", &n);
for(i = ; i < n; i++)
{
scanf("%s", a);
l = strlen(a);
for(j = ; j < l; j++) belong[len] = i, s[len++] = a[j];
belong[len] = i;
s[len++] = + (i << );
for(j = l - ; j >= ; j--) belong[len] = i, s[len++] = a[j];
belong[len] = i;
s[len++] = + (i << | );
}
len--;
build_sa();
build_height();
if(n == )
{
printf("%d\n", l);
continue;
}
printf("%d\n", solve());
}
return ;
}
[POJ1226]Substrings(后缀数组)的更多相关文章
- POJ1226 Substrings ——后缀数组 or 暴力+strstr()函数 最长公共子串
题目链接:https://vjudge.net/problem/POJ-1226 Substrings Time Limit: 1000MS Memory Limit: 10000K Total ...
- POJ1226:Substrings(后缀数组)
Description You are given a number of case-sensitive strings of alphabetic characters, find the larg ...
- UVALive - 6869 Repeated Substrings 后缀数组
题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- SPOJ - SUBST1 New Distinct Substrings —— 后缀数组 单个字符串的子串个数
题目链接:https://vjudge.net/problem/SPOJ-SUBST1 SUBST1 - New Distinct Substrings #suffix-array-8 Given a ...
- SPOJ- Distinct Substrings(后缀数组&后缀自动机)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- SPOJ - DISUBSTR Distinct Substrings (后缀数组)
Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- SPOJ DISUBSTR Distinct Substrings 后缀数组
题意:统计母串中包含多少不同的子串 然后这是09年论文<后缀数组——处理字符串的有力工具>中有介绍 公式如下: 原理就是加上新的,减去重的,这题是因为打多校才补的,只能说我是个垃圾 #in ...
- ●SPOJ 8222 NSUBSTR - Substrings(后缀数组)
题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 同届红太阳 --WSY给出的后缀数组解法!!! 首先用倍增算法求出 sa[i],rak[i],hei[i]然 ...
随机推荐
- Kernel trick----PRML读书笔记
Many linear parametric models can be re-cast into an equivalent 'dual representstion' in which the p ...
- bzoj3011
可并堆 复习一下可并堆 维护一个大跟堆,每次把节点儿子打上边权标记,然后合并,可并堆上维护一个size,每次把大于l的弹出,size就是答案 程序中那个d写l和r速度差不多,我写l是表示右儿子到u的最 ...
- 入门activiti-------1简单运行
1.下载原料 2.放置位置 3.运行 4.成功页面和测试数据
- discuz的cutstr函数
function cutstr($string, $length, $dot = ' ...') { if(strlen($string) <= $length) { return $strin ...
- [Swift通天遁地]六、智能布局-(6)其他几种约束关系:父视图/Corner/Edge/AnchorAndFillEdge
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- SpringCloud服务组合
SpringCloud生态强调微服务,微服务也就意味着将各个功能独立的业务抽象出来,做成一个单独的服务供外部调用.但每个人对服务究竟要有多“微”的理解差异很大,导致微服务的粒度很难掌控,划分规则也不统 ...
- css选择器---继承,优先级,层叠
CSS三大特性—— 继承. 优先级和层叠. 继承:即子类元素继承父类的样式; 优先级:是指不同类别样式的权重比较; 层叠:是说当数量相同时,通过层叠(后者覆盖前者)的样式. css选择符分类 首先来看 ...
- Spring Cloud (6) 分布式配置中心-高可用
高可用 现在已经可以从配置中心读取配置文件了,当微服务很多时都从配置中心读取配置文件,这时可以将配置中心做成一个微服务,将其集群化,从而达到高可用. 改造config-server 加入eureka ...
- SublimeText学习(二)-基本操作
1.查看已安装的插件 看到已经安装的插件,看到了在上一篇中安装的Emmet 2.设置主题与字体 方法一: 方法二: 工具栏中 [Preference-浏览程序包]找到[Default文件夹]-用Sub ...
- js面试笔试题
1. Js的Typeof返回类型有那些? string:undefined:number; function:object:boolean:symbol(ES6) 2. null和undefined的 ...