HDU 5008 Boring String Problem(后缀数组+二分)
思路 想到了,但是木写对啊....代码 各种bug,写的乱死了....
输出最靠前的,比较折腾...
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
#define N 501000
#define LL __int64
int sa[N],height[N],rank[N];
int c[N],wa[N],wb[N];
int p[N];
int res[N];
char str[N];
LL sum[N];
LL l,r;
int bin[];
int minz[][N];
int sz[][N];
void build_sa(int s[],int n,int m)
{
int i,j,p,*x = wa,*y = wb;
for(i = ;i < m;i ++)
c[i] = ;
for(i = ;i < n;i ++)
c[x[i] = s[i]] ++;
for(i = ;i < m;i ++)
c[i] += c[i-];
for(i = n-;i >= ;i --)
sa[--c[x[i]]] = i;
for(j = ;j <= n;j <<= )
{
p = ;
for(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 < m;i ++)
c[i] = ;
for(i = ;i < n;i ++)
c[x[y[i]]] ++;
for(i = ;i < m;i ++)
c[i] += c[i-];
for(i = n-;i >= ;i --)
sa[--c[x[y[i]]]] = y[i];
swap(x,y);
p = ;x[sa[]] = ;
for(i = ;i < n;i ++)
x[sa[i]] = y[sa[i-]] == y[sa[i]]&&y[sa[i-]+j] == y[sa[i]+j]?p-:p++;
if(p >= n) break;
m = p;
}
}
void get_height(int s[],int n)
{
int i,j,k = ;
for(i = ;i <= n;i ++)
rank[sa[i]] = i;
for(i = ;i < n;i ++)
{
if(k) k--;
j = sa[rank[i]-];
while(s[i+k]==s[j+k]) k ++;
height[rank[i]] = k;
}
}
void init(int n)
{
int i,j;
for(i = ; i <= n; i ++)
{
minz[][i] = height[i];
sz[][i] = sa[i];
}
for(i = ; bin[i] <= n; i ++)
{
for(j = ; j + bin[i-] <= n; j ++)
{
minz[i][j] = min(minz[i-][j],minz[i-][j+bin[i-]]);
sz[i][j] = min(sz[i-][j],sz[i-][j+bin[i-]]);
}
}
}
int rmq(int s,int t)
{
s = rank[s];
t = rank[t];
if(s > t) swap(s,t);
s ++;
int k = log((t-s+)*1.0)/log(2.0);
return min(minz[k][s],minz[k][t-bin[k]+]);
}
int rmq1(int s,int t)
{
s = rank[s];
t = rank[t];
if(s > t) swap(s,t);
s ++;
int k = log((t-s+)*1.0)/log(2.0);
return min(sz[k][s],sz[k][t-bin[k]+]);
}
void find(LL k,int n)
{
int str,end,mid,i;
str = ;
end = n;
while(str < end)
{
mid = (str + end + )/;
if(sum[mid] > k)
end = mid - ;
else
str = mid;
}
i = end;
if(sum[end] > k)
{
l = sa[i];
r = sa[i]+k-;
}
else if(k == sum[end])
{
l = sa[i];
r = n-;
}
else
{
i ++;
l = sa[i];
r = sa[i] + k - sum[end] + height[i]-;
}
int len = r-l+;
if(i == n)
{
l ++;
r ++;
return ;
}
if(height[i+] < len)
{
l ++;
r ++;
return ;
}
str = i+;
end = n;
while(str < end)
{
mid = (str + end + )/;
if(rmq(sa[i],sa[mid]) < len)
end = mid - ;
else
str = mid;
}
if(rmq(sa[i],sa[end]) >= len)
{
l = min(l,(LL)rmq1(sa[i],sa[end]));
r = l+len-;
}
l ++;
r ++;
}
int main()
{
int i,len,n;
LL maxz;
for(i = ; i < ; i ++)
bin[i] = <<i;
LL v,k;
while(scanf("%s",str)!=EOF)
{
len = strlen(str);
for(i = ;i < len;i ++)
{
p[i] = str[i]-'a'+;
}
p[len] = ;
build_sa(p,len+,);
get_height(p,len);
init(len);
maxz = ;
for(i = ;i <= len;i ++)
{
maxz += len-sa[i]-height[i];
sum[i] = maxz;
}
scanf("%d",&n);
l = r = ;
for(i = ;i < n;i ++)
{
scanf("%I64d",&v);
// find(v,len);
// printf("%I64d %I64d\n",l,r);
k = (v^l^r)+; if(k > maxz)
{
l = r = ;
}
else
{
find(k,len);
}
printf("%I64d %I64d\n",l,r);
}
}
return ;
}
HDU 5008 Boring String Problem(后缀数组+二分)的更多相关文章
- HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)
Problem Description In this problem, you are given a string s and q queries. For each query, you sho ...
- HDU 5008 Boring String Problem
题意:给定一个串长度<=1e5,将其所有的不同的字串按照字典序排序,然后q个询问,每次询问字典序第k小的的起始坐标,并且起始坐标尽量小. 分析: 一开始看错题意,没有意识到是求不同的字串中第k小 ...
- HDU5008 Boring String Problem(后缀数组)
练习一下字符串,做一下这道题. 首先是关于一个字符串有多少不同子串的问题,串由小到大排起序来应该是按照sa[i]的顺序排出来的产生的. 好像abbacd,排序出来的后缀是这样的 1---abbacd ...
- HDOJ 5008 Boring String Problem
后缀数组+RMQ+二分 后缀数组二分确定第K不同子串的位置 , 二分LCP确定可选的区间范围 , RMQ求范围内最小的sa Boring String Problem Time Limit: 6000 ...
- HDU 3518 Boring counting(后缀数组,字符处理)
题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
随机推荐
- git diff 生成patch, git apply patch 打补丁方法说明,以及分支管理的简单操作。
git diff 简易操作说明 先git log 查看commit ID, 记录你想要打的补丁的ID 比如说: git log commit 4ff35d800fa62123a28b7bda2a04e ...
- 在一个aspx或ashx页面里进行多次ajax调用
在用ajax开发asp.net程序里.利用ashx页面与前台页面进行数据交互.但是每个ajax交互都需要一个ashx页面.结果是项目里一大堆ashx页面.使项目难以管理.现在我们就想办法让一个ashx ...
- Java内存管理及GC算法
概述 内存划分 虚拟机规范中将内存分为六大部分,分别为PC寄存器.JAVA虚拟机栈.JAVA堆.方法区.运行时常量及本地方法栈. 1.PC寄存器:线程独占: 2.JAVA虚拟机栈:线程独有:JAVA虚 ...
- NodeJS 最快速搭建一个HttpServer
最快速搭建一个HttpServer 在目录里放一个index.html cd D:\Web\InternalWeb start http-server -i -p 8081
- .net测试学习--理解.net测试选项
1.创建基于测试简单应用程序 (1)启动visual studio(有安装c#的) (2) 选择File|New project (3)创建一个C# project,名字和保存路径自己设定,假设取名 ...
- java类加载器加载文件
例子:采用配置文件加反射的方式创建ArrayList和HashSet的实例对象. //第一种方式:类加载器加载文件 InputStream ips = ReflectTest2.class.getCl ...
- BOOST_AUTO宏
在boost中,有个非常不错的宏BOOST_AUTO(),它的作用是自动给var定义类型,适合function()函数返回的值的类型. int function() { ; } main() { BO ...
- Redis Sentinel集群配置中的一些细节
今天在配置Redis集群,用作Tomcat集群的缓存共享.关于Redis集群的配置网上有很多文章,这里只是记录一下我在配置过程中遇到的一些小的细节问题. 1. 关于Protected Mode的问题 ...
- HTML5窗口间同域和跨域的通信
一丶同域下的 1.如果我们要操作iframe里面的元素,首先获取到引入的页面的window.获取iframe里面的window对象. var oIframe=getElementsByTagName( ...
- ExtJs基础知识总结:Dom、IFrame和TreePanel、TabPanel(三)
概述 ExtJs是另外一种操作封装JavaScript的类库与Jquery同类.所以对Dom的操作也是支持的,比如修改Div内Html内容等操作.有几个问题需要思考下: 1.ExtJs也支持IFram ...