RMQ即求区间(i,j)的最值。通过O(nlogn)处理,O(1)给出答案。

RMQ主要是动态规划来做。dp[i][j]表示从i开始的长为2^j的区间最值。

那么可以得到dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);

dp[i][j],这个区间可以分为2段(可以重叠),那最值就是这两段的最值。

查询时要找到那个j,那j=(int)(log((y-x+1)*1.0)/log(2.0));

对于求回文 可以转变为当前的位子进行枚举 求当前的位置的后缀和当前位置的前面部分的公共长度,又前面一部分就是在后面添加的2*n-i的位置
所以只要求出height[i+1.....2*n-i]的最小值,这里就用到RMQ来做;

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
//#include<Windows.h>
#define maxn 2100
#define LL long long
using namespace std;
int wa[maxn],wb[maxn],wv[maxn],WS[maxn],n;
int dp[maxn][];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
int min(int x,int y)
{return x<y?x:y;}
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];
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],sa[maxn];
void RMQ()
{
int i,j;
memset(dp,,sizeof(dp));
for(i=;i<=*n+;i++)
dp[i][]=height[i];
for(j=;j<=;j++)
for(i=;i+(<<j)-<=*n+;i++)
{
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
}
}
int lcp(int left,int right)
{
int a=Rank[left];
int b=Rank[right];
if(a>b)
{
int t=a;
a=b;
b=t;
}
a++;
int k=(int)(log((b-a+)*1.0)/log(2.0));
return min(dp[a][k],dp[b-(<<k)+][k]);
}
char s[maxn];
int main()
{
int i,j;
scanf("%s",s);
n=strlen(s);
s[n]='#';
int len=n+;
for(i=n-;i>=;i--)
s[len++]=s[i];
//printf("%s\n",s);
for(i=;i<*n+;i++)
r[i]=s[i];
r[*n+]=;
da(r,sa,n*+,);
calheight(r,sa,n*+);
RMQ();
int ans=-;
int set=;
int res;
//对于求回文 可以转变为当前的位子进行枚举 求当前的位置的后缀和当前位置的前面部分的公共长度,又前面一部分就是在后面添加的2*n-i的位置
//所以只要求出height[i+1.....2*n-i]的最小值
for(i=;i<n;i++)
{
res=lcp(i,*n-i)*-;//对于奇数
if(res>ans)
{
ans=res;
set=i;
}
res=lcp(i,*n-i+)*;//对于偶数
if(res>ans)
{
ans=res;
set=i;
}
}
if(ans%)
{
for(i=set-ans/;i<=set+ans/;i++)
{
printf("%c",s[i]);
}
}
else
{
for(i=set-ans/;i<=set+ans/-;i++)
{
printf("%c",s[i]);
}
}
printf("\n");
//system("pause");
}

ural1297 后缀数组+RMQ的更多相关文章

  1. 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过

    题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...

  2. POJ 3693 后缀数组+RMQ

    思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...

  3. spoj687 REPEATS - Repeats (后缀数组+rmq)

    A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed strin ...

  4. Ural1297 最长回文子串(后缀数组+RMQ)

    /* 源程序丢失QWQ. 就不粘代码了. 大体做法是把串反转然后连接. 做一遍后缀数组. 对height做一遍rmq. 然后对于每个位置的奇偶分别判断, 记下pos. 注意求的是[l+1,r]的hei ...

  5. HDU2459 后缀数组+RMQ

    题目大意: 在原串中找到一个拥有连续相同子串最多的那个子串 比如dababababc中的abababab有4个连续的ab,是最多的 如果有同样多的输出字典序最小的那个 这里用后缀数组解决问题: 枚举连 ...

  6. hdu 2459 (后缀数组+RMQ)

    题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...

  7. ural 1297(后缀数组+RMQ)

    题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文. 思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能 ...

  8. 【BZOJ 3473】 字符串 (后缀数组+RMQ+二分 | 广义SAM)

    3473: 字符串 Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串 ...

  9. 【poj3693】Maximum repetition substring(后缀数组+RMQ)

    题意:给定一个字符串,求重复次数最多的连续重复子串. 传说中的后缀数组神题,蒟蒻真的调了很久才对啊.感觉对后缀数组和RMQ的模版都不是很熟,导致还是会有很多各种各样的小错误= = 首先,枚举重复子串的 ...

随机推荐

  1. PHP实现定时任务(非linux-shell方式,与操作系统无关)

    页面交互效果 下面是写好的示例前端交互页面,主要是列表页面,编辑页面. 主要交互有: 1 开启定时任务进程 2 关闭定时任务进程 3 新增一项定时任务 4 编辑已有的定时任务 5 删除定时任务 6 开 ...

  2. css3之文本和颜色功能之text-overflow,word-wrap

    语法 text-overflow: clip|ellipsis|string; clip修剪文本.ellipsis显示省略符号来代表被修剪的文本.string使用给定的字符串来代表被修剪的文本. 效果 ...

  3. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  4. golang包引用

    一.我的GOPATH环境变量值如下图: 二.在GOPATH路径下面的的src目录下面的目录名称就是引用里面包的起始位置,如下图: 三.举例说明:这里引用同一个项目的包,源文件“learn/main/m ...

  5. Redis源码解析:16Resis主从复制之主节点的完全重同步流程

    主从复制过程中,主节点根据从节点发来的命令执行相应的操作.结合上一章中讲解的从节点在主从复制中的流程,本章以及下一篇文章讲解一下主节点在主从复制过程中的流程. 本章主要介绍完全重同步流程. 一:从节点 ...

  6. web前端学习(四)JavaScript学习笔记部分(8)-- JavaScript 浏览器对象

    1.window对象 1.1.window对象: window对象是BOM的核心,window对象指当前的浏览器窗口 所有javaScript全局对象.函数以及变量均自动生成为window对象的成员 ...

  7. Idea代理设置与Java程序的代理设置

    最近在学习WebService的过程中,为了弄清楚发送和接收的包的数据结构,使用Fiddler抓取包的数据.开始先配置了Idea的代理设置,但执行Java代码发送请求时,依然无法在Fiddler中抓取 ...

  8. proteus 8.8 直装版提示Symbol $MKRORIGIN used but not found in libraries 安装后没有库

    用管理员运行程序,然后再通过菜单打开仿真文件是没问题. 解决方法:通常的安装目录是C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Prof ...

  9. LinqToExcel 简洁与优美开源库

    转载:https://www.cnblogs.com/codefish/archive/2013/04/08/3009098.html 正在做项目,同事问道有啥简单的方法读取excel到DataTab ...

  10. idea展开和折叠方法的快捷键

    Ctrl+"+/-",当前方法展开.折叠 Ctrl+Shift+"+/-",全部展开.折叠