当初合肥区域赛的题(现场赛改了数据范围就暴力过了),可惜当初后缀数组算法的名字都没听过,现在重做下。

i从1到n - 1,每次枚举rank[i]附近的排名,并记录当起点小于i时的LCP(rank[i], d)的最大值,或是在LCP不变时更新起点。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int N = 110008, INF = 0x3F3F3F3F; int val[N], ws0[N], wa[N], wb[N];
int sa[N], rk[N], height[N]; char str[N]; bool cmp(int str[], int a, int b, int l){
return str[a] == str[b] && str[a + l] == str[b + l];
} void da(char str[], int n, int m){
int *x = wa, *y = wb; memset(ws0, 0, sizeof(ws0));
for(int i = 0; i < n; i++)
ws0[x[i] = str[i]]++; for(int i = 1; i < m; i++)
ws0[i] += ws0[i - 1]; for(int i = n - 1; i >= 0; i--)
sa[--ws0[ x[i]] ] = i; for(int j = 1, p = 1; p < n; j *= 2, m = p){
p = 0;
for(int i = n - j; i < n; i++)
y[p++] = i;
for(int i = 0; i < n; i++)
if(sa[i] >= j)
y[p++] = sa[i] - j;
for(int i = 0; i < n; i++)
val[i] = x[ y[i] ]; memset(ws0, 0, sizeof(ws0));
for(int i = 0; i < n; i++)
ws0[val[i]]++; for(int i = 1; i < m; i++)
ws0[i] += ws0[i - 1]; for(int i = n - 1; i >= 0; i--)
sa[--ws0[ val[i] ]] = y[i]; swap(x, y);
x[sa[0]] = 0;
p = 1;
for(int i = 1; i < n; i++)x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1:p++;
}
} void calHeight(char str[], int n){
for(int i = 1; i <= n; i++){
rk[ sa[i] ] = i;
}
int k = 0;
for(int i = 0; i < n; i++){
if(k){
k--;
}
int j = sa[rk[i] - 1];
while(str[i + k] == str[j + k]){
k++;
}
height[rk[i]] = k;
}
} int rmq[N][20], tab[N]; void initaskRMQ(int n){
tab[1] = 0;
for(int i = 2; i <= n; i++){
tab[i] = ( (i & (i - 1)) == 0)? tab[i - 1] + 1:tab[i - 1];
}
for(int i = 1; i <= n; i++){
rmq[i][0] = height[i];
}
for(int i = 1; i <= tab[n]; i++){
for(int j = 1; j <= n + 1 - (1 << i); j++){
int a = rmq[j][i - 1];
int b = rmq[j + (1 <<(i - 1))][i - 1];
rmq[j][i] = min(a, b);
}
}
} int askRMQ(int a, int b){
int k = tab[b -a + 1];
b -= (1 << k ) - 1;
return min(rmq[a][k], rmq[b][k]);
} int LCP(int a, int b){
if(a > b){
swap(a, b);
}
return askRMQ(a + 1, b);
} int main(){
int t;
cin>>t;
for(int cas = 1; cas <= t; cas++){
scanf("%s", str);
int n = strlen(str);
da(str, n + 1, 'z' + 1);
calHeight(str, n); initaskRMQ(n);
printf("Case #%d:\n", cas);
printf("%d %d\n", -1, str[0]);
for(int i = 1; i < n; ){
int st = INF, k = 1;
int d = rk[i] + 1;
int tp;
while(d <= n && (tp = LCP(d, rk[i])) >= k){
if(sa[d] < i){
if(tp > k){
k = tp;
st = sa[d];
}else{
if(sa[d] < st){
st = sa[d];
}
}
}
d++;
} d = rk[i] - 1;
while(d >= 1 && (tp = LCP(d, rk[i])) >= k){
if(sa[d] < i){
if(tp > k){
k = tp;
st = sa[d];
}else{
if(sa[d] < st){
st = sa[d];
}
}
}
d--;
}
if(st < i){
printf("%d %d\n", k, st);
i += k;
}else{
printf("%d %d\n", -1, (int)str[i]);
i++;
}
}
}
return 0;
}

  加油吧! fighting!!!

HDU5558 Alice's Classified Message(合肥区域赛 后缀数组)的更多相关文章

  1. hdu5558 Alice's Classified Message

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5558 题目: Alice's Classified Message Time Limit: 1 ...

  2. (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...

  3. HDU5556 Land of Farms(二分图 2015 合肥区域赛)

    容易想到将问题转化为求图的独立数问题 ,但求一般图的独立集是一个NPC问题,需要一些转化. 状态压缩,枚举每个上古农场是否选择,然后将剩下的新农场根据i + j奇偶性分为x , y集. 结果为 max ...

  4. HUID 5558 Alice's Classified Message 后缀数组+单调栈+二分

    http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做 ...

  5. 【HDOJ5558】Alice's Classified Message(后缀数组)

    题意:给定一个长度为n的下标从0开始的小写字母字符串,每次对于当前的i寻找一个j使得后缀i与后缀j的lcp最大,(j<i)若lcp相同则取较小的 若lcp为0则输出0与当前字符,i自增1,否则输 ...

  6. Alice's Classified Message HDU - 5558 后缀自动机求某个后缀出现的最早位置

    题意: 给定一个长度不超过 10W 的只包含小写字母的字符串,从下标 0 到 n−1.从下标 0 开始操作, 每次对于下标 pos查找下标 pos 开始的子串中最长的在其他地方出现过的长度,其他出现的 ...

  7. HDU 5558 Alice's Classified Message(后缀数组+二分+rmq(+线段树?))

    题意 大概就是给你一个串,对于每个\(i\),在\([1,i-1]\)中找到一个\(j\),使得\(lcp(i,j)\)最长,若有多个最大\(j\)选最小,求\(j\)和这个\(lcp\)长度 思路 ...

  8. POJ.2774.Long Long Message/SPOJ.1811.LCS(后缀数组 倍增)

    题目链接 POJ2774 SPOJ1811 LCS - Longest Common Substring 比后缀自动机慢好多(废话→_→). \(Description\) 求两个字符串最长公共子串 ...

  9. HDU 6194 string string string 2017沈阳网络赛 后缀数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6194 题意:告诉你一个字符串和k , 求这个字符串中有多少不同的子串恰好出现了k 次. 解法:后缀数组 ...

随机推荐

  1. 前端之css、JavaScript和DOM

    css position 一般组合 relative+absolute,以relative为父元素,absolute依照relative进行定位. opcity: 0.5 透明度 z-index: 层 ...

  2. Java 日期加减计算.

    1.用Java.util.Calender来实现 Calendar calendar=Calendar.getInstance();      calendar.setTime(new Date()) ...

  3. Js 的 this 是什么

    this指的是调用函数的那个对象,谁调用函数,谁就是this 更多: http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_thi ...

  4. CentOS 下安装xdebug

    在CentOS 6.x 的系统中,是集成xdebug 的, yum install PHP-pecl-xdebug 如果是CentOS.5 也可能通过安装安装 epel 来安装 rpm -ivh ht ...

  5. VirtualBox中安装Ubuntu12.04/Ubuntu14.04虚拟机

    NOTE: 一开始安装的Ubuntu12.04,后来又重新安装了14.04.截图基本使用了安装12.04时的截图,后来安装14.04时又补充了几张.该安装过程对Ubuntu12.04和14.04都是适 ...

  6. C#之类的继承、抽象类和虚方法

    代码下载地址 类的继承: 写电池的基类:包含条码和箱体码两个字段,含有两个参数的构造函数 class Battery { public string _barCode; public string _ ...

  7. Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值

    Delphi Cxgrid获取选中行列,排序规则,当前正在编辑的单元格内的值 cxGrid1DBTableView1.Controller.FocusedRowIndex 当前行号 cxGrid1DB ...

  8. TokuDB 引擎安装测试

    背景: TokuDB引擎是有Tokutek开发的一个数据库存储引擎,在设计之初便引入了独特的索引算法,在其官网测试的文章中看到TokuDB性能比InnoDB高出很多. MySQL是一个插件式的数据库, ...

  9. Divide and conquer:Telephone Lines(POJ 3662)

    电话线 题目大意:一堆电话线要你接,现在有N个接口,总线已经在1端,要你想办法接到N端去,电话公司发好心免费送你几段不用拉网线,剩下的费用等于剩余最长电话线的长度,要你求出最小的费用. 这一看又是一个 ...

  10. IT笔试题

    史上最发散的软件工程师笔试题 1.请编写代码实现如下逻辑:有一只猫和多只老鼠,猫叫了一声,老鼠都吓跑了. 2.请介绍一种数据结构和算法,代表你在这个领域的能力. 3.请从正反两面介绍一下你对代码质量的 ...