题目链接:http://poj.org/problem?id=1226

题意:给定n个字符串[只含大小写字母],求一个字符串要求在n个串或者他们翻转后的串的出现过。输出满足要求的字符串的长度

思路:根据<<后缀数组——处理字符串的有力工具>>的思路,这题不同的地方在于要判断是否在反转后的字符串中出现 。其实这并没有加大题目的难度 。 只需要先将每个字符串都反过来写一遍, 中间用一个互不相同的且没有出现在字符串中的字符隔开,再将 n个字符串全部连起来, 中间也是用一 个互不相同的且没有出现在字符串中的字符隔开, 求后缀数组 。 然后二分答案ans, 再将后缀分组,每组后缀的值都不小于ans。 判断的时候, 要看是否有一组后缀在每个原来的字符串或反转后的字符串中出现。这个做法的时间复杂度为 0(nlogn) 。

因为题目数据不大,所以也可以用二分+kmp来做。

#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];
char str[+];
bool check(int x){
set<int>se;
for (int i = ; i < len; i++){
if (height[i] >= x){ //分组,把每组属于哪个原串保存在集合
se.insert(Index[sa[i]]); se.insert(Index[sa[i - ]]);
}
else{//一组的分界线,判断是否有n个串都存在集合中
if (se.size() == n){ return true; } se.clear();
}
}
if (se.size() == n){ return true; }
return false;
}
void solve(){
if (n == ){ //注意特判n=1!
printf("%d\n", strlen(str));
return;
}
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++){
scanf("%s", &str);
for (int j = ; j < strlen(str); j++){ //正序
Index[len] = i;
r[len++] = (str[j] - 'A' + * n + );
}
Index[len] = i;
r[len++] = val++; //不同的字符隔开
for (int j = strlen(str) - ; j >= ; j--){ //翻转
Index[len] = i;
r[len++] = (str[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 ;
}

POJ 1226 后缀数组的更多相关文章

  1. poj 3693 后缀数组 重复次数最多的连续重复子串

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8669   Acc ...

  2. POJ - 3294~Relevant Phrases of Annihilation SPOJ - PHRASES~Substrings POJ - 1226~POJ - 3450 ~ POJ - 3080 (后缀数组求解多个串的公共字串问题)

    多个字符串的相关问题 这类问题的一个常用做法是,先将所有的字符串连接起来, 然后求后缀数组 和 height 数组,再利用 height 数组进行求解. 这中间可能需要二分答案. POJ - 3294 ...

  3. poj 3261 后缀数组 找反复出现k次的子串(子串能够重叠)

    题目:http://poj.org/problem?id=3261 仍然是后缀数组的典型应用----后缀数组+lcp+二分 做的蛮顺的,1A 可是大部分时间是在调试代码.由于模板的全局变量用混了,而自 ...

  4. POJ 3415 后缀数组

    题目链接:http://poj.org/problem?id=3415 题意:给定2个串[A串和B串],求两个串公共子串长度大于等于k的个数. 思路:首先是两个字符串的问题.所以想用一个'#'把两个字 ...

  5. POJ 3450 后缀数组/KMP

    题目链接:http://poj.org/problem?id=3450 题意:给定n个字符串,求n个字符串的最长公共子串,无解输出IDENTITY LOST,否则最长的公共子串.有多组解时输出字典序最 ...

  6. POJ 3294 后缀数组

    题目链接:http://poj.org/problem?id=3294 题意:给定n个字符串,求一个最长子串要求在超过一半的字符串中出现过. 如果多解按字典序输出 思路:根据<<后缀数组— ...

  7. POJ 2774 后缀数组

    题目链接:http://poj.org/problem?id=2774 题意:给定两个只含小写字母的字符串,求字符串的最长公共子串长度. 思路:根据<<后缀数组——处理字符串的有力工具&g ...

  8. POJ 3693 后缀数组

    题目链接:http://poj.org/problem?id=3693 题意:首先定义了一个字符串的重复度.即一个字符串由一个子串重复k次构成.那么最大的k即是该字符串的重复度.现在给定一个长度为n的 ...

  9. POJ 3261 后缀数组

    题目链接:http://poj.org/problem?id=3261 题意:约翰注意到奶牛产奶的之类是不断变化的,虽然他不能预测从当天到下一天的变化情况但是他知道变化是有规律的,牛奶的质量由一个整数 ...

随机推荐

  1. 通过configSource提高web.config配置灵活性

    很多时候我们会有这样的情况,开发环境和测试环境中的配置文件是不一样的,最明显的就是数据库连接串,这样,每次我们发布一个测试版本,都要手动去修改一下配置文件,是不是很麻烦的说.其实利用web.confi ...

  2. poj 3735 Training little cats 矩阵快速幂+稀疏矩阵乘法优化

    题目链接 题意:有n个猫,开始的时候每个猫都没有坚果,进行k次操作,g x表示给第x个猫一个坚果,e x表示第x个猫吃掉所有坚果,s x y表示第x个猫和第y个猫交换所有坚果,将k次操作重复进行m轮, ...

  3. Xn数列(codevs 1281)

    题目描述 Description 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn m, a, c, x0, n, g<=10^18 输入 ...

  4. Mysql之取消主从复制

    Mysql5.7 Mysql取消主从复制很简单.只需在其要终止同步的Server上[一般是Slave]执行下面语句即可: stop slave; reset slave; 如图: .

  5. Bootstrap学习(一)

    Bootstrap就是对jQuery的一次再开发,所以jQuery脚本引用必须在bootstrap脚本之前. 链接:http://www.cnblogs.com/vvjiang/p/5189804.h ...

  6. 001课-java_web开发入门

    一.Tomcat服务器常见启动问题:(1).Java_home环境变量,由于tomcat服务器的bin目录中的一些jar文件必须使用到java类库,所以必须先配置Java_home环境变量.(2).端 ...

  7. HBase参数配置及说明(转)

    版本:0.94-cdh4.2.1 hbase-site.xml配置 hbase.tmp.dir 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很多文件都会默 ...

  8. maven入门基础(转)

    maven介绍 maven是构建工具,也是构建管理工具.ant只是构建工具,因为不支持生成站点功能,只有预处理,编译,打包,测试,部署等功能. maven坐标 groupId:项目组织的逆向域名,比如 ...

  9. Android -- java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available

    使用Bundle 的getParcelableArray 出现了以下错误: Class not found when unmarshallingjava.lang.ClassNotFoundExcep ...

  10. gzip

    gzip -c 将输出写到标准输出上,并保留原文本 gzip * : 把当前目录中的每个文件压缩成.gz文件 [root@NB gzip]# ls mysql-bin. mysql-bin..tar ...