ural 1297(后缀数组+RMQ)
题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文。
思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能出现的字符隔开。然后就用到后缀数组的性质了,
我们枚举每一个原始字符串中的字符以它为中心(分为奇数和偶数两种情况)进行查找,比如对于下标为i的字符,当回文串为奇数时,我们要求的就是i的后缀与2*n-i的
后缀的最长公共前缀了,然后根据height数组的性质就转化成求height[i+1]...height[2*n-i]中的最小值了,这时我们想到了用RMQ求区间最值了,对于不会RMQ的童
鞋可以先去学习下,再来做这道题,具体看代码实现:
代码实现:
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
#define N 2010
int ws1[N],wv[N],wa[N],wb[N];
int rank1[N],height[N],sa[N];
char str[N];
int a[N],n;
int dp[N][]; int min(int a,int b)
{
return a>b?b:a;
} 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++)
ws1[i]=;
for(i=;i<n;i++)
ws1[x[i]=r[i]]++;
for(i=;i<m;i++)
ws1[i]+=ws1[i-];
for(i=n-;i>=;i--)
sa[--ws1[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++)
ws1[i]=;
for(i=;i<n;i++)
ws1[wv[i]]++;
for(i=;i<m;i++)
ws1[i]+=ws1[i-];
for(i=n-;i>=;i--)
sa[--ws1[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++;
}
} void calheight(int *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++)
rank1[sa[i]]=i;
for(i=;i<n;height[rank1[i++]]=k)
for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++) ;
} void RMQ()//RMQ预处理
{
int i,j;
memset(dp,,sizeof(dp));
for(i=;i<=n*+;i++)
dp[i][]=height[i];
for(j=;(<<j)<=*n+;j++)
for(i=;i+(<<j)-<=*n+;i++)
dp[i][j]=min(dp[i][j-],dp[i+(<<(j-))][j-]);
} int lcp(int l,int r)//求最长公共前缀
{
int a=rank1[l],b=rank1[r];
if(a>b)
swap(a,b);
a++;
int t=(int)(log(double(b-a+))/log(2.00));
return min(dp[a][t],dp[b-(<<t)+][t]);
} int main()
{
int i,res,flag,max;
while(scanf("%s",str)!=EOF)
{
max=;
n=strlen(str);
for(i=;i<n;i++)
a[i]=(int)str[i];
a[n]=;
for(i=;i<n;i++)
a[i+n+]=int(str[n-i-]);
a[*n+]=;
da(a,sa,n*+,);
calheight(a,sa,*n+);
RMQ();
for(i=;i<n;i++)
{
res=lcp(i,*n-i)*-;
if(max<res)//奇数时
{
max=res;
flag=i;
}
if(i>)//偶数时
{
res=lcp(i,*n-i+)*;
if(max<res)
{
max=res;
flag=i;
}
}
}
if(max%==)
for(i=flag-max/;i<=flag+max/;i++)
printf("%c",str[i]);
else
for(i=flag-max/;i<=flag+max/-;i++)
printf("%c",str[i]);
printf("\n");
}
return ;
}
ural 1297(后缀数组+RMQ)的更多相关文章
- URAL 1297 后缀数组:求最长回文子串
思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. ...
- URAL - 1297 后缀数组的做法 LCP应用
题意:求最长回文子串 这种有专门的O(n)套板子算法,但作为练习还是用后缀数组来解吧 只需把相同的另一个串反接(中间用一个足够小且未出现的字符衔接),然后枚举回文串的中点,不断求解该点往前和往后计算的 ...
- ural 1297 后缀数组 最长回文子串
https://vjudge.net/problem/URAL-1297 题意: 给出一个字符串求最长回文子串 代码: //论文题,把字符串反过来复制一遍到后边,中间用一个没出现的字符隔开,然后就是枚 ...
- URAL 1297 后缀数组+线段树
思路: 论文题--*n 倒过来接上 分奇偶讨论 求LCP 搞棵线段树即可 //By SiriusRen #include <cstdio> #include <cstring> ...
- 【uva10829-求形如UVU的串的个数】后缀数组+rmq or 直接for水过
题意:UVU形式的串的个数,V的长度规定,U要一样,位置不同即为不同字串 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&am ...
- POJ 3693 后缀数组+RMQ
思路: 论文题 后缀数组&RMQ 有一些题解写得很繁 //By SiriusRen #include <cmath> #include <cstdio> #includ ...
- 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 ...
- HDU2459 后缀数组+RMQ
题目大意: 在原串中找到一个拥有连续相同子串最多的那个子串 比如dababababc中的abababab有4个连续的ab,是最多的 如果有同样多的输出字典序最小的那个 这里用后缀数组解决问题: 枚举连 ...
- hdu 2459 (后缀数组+RMQ)
题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...
随机推荐
- [C++]虚函数-同名访问
首先来看一下派生类和基类成员同名事的处理规则: 派生类内定义了一个与基类同名的成员,该现象称为同名覆盖,此时,无论派生类内部成员函数还是派生类的对象访问同名成员,如果未加任何特殊标识,则访问派生类中重 ...
- ****Git 常用命令和使用思维导图
Git 是一个很强大的分布式版本控制系统.它不但适用于管理大型开源软件的源代码,管理私人的文档和源代码也有很多优势. 本来想着只把最有用.最常用的 Git 命令记下来,但是总觉得这个也挺有用.那个也用 ...
- django --fields.E304 错误解决方案
今天在同一个表里,有多个不同的用户集时出现. fields.E304: Field name <field name> clashes with accessor for <fiel ...
- 深入浅出Java并发包—锁机制(二)
接上文<深入浅出Java并发包—锁机制(一) > 2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tr ...
- XML中如何使用schema
Schema简介 DTD的语法相当复杂,并且它不符合XML文件的标准,自成一个体系,W3C定义的Schema用来代替DTD. chema相对于DTD的明显好处是XML Schema文档本身也是XML文 ...
- 李洪强iOS开发之OC[015]#pragma mark的使用
// // main.m // 14 - #pragma mark的使用 // // Created by vic fan on 16/7/10. // Copyright © 2016年 李 ...
- 【Linux高频命令专题(22)】gzip
概述 减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅 ...
- 1、Singleton 单件(创建模式)
一.Singleton模式主要应用在一些特殊的类,在整个系统运行中,有且仅有一个实例的场景 二.Singleton模式分为单线程与多线程情况,当然多线程一样适应单线程 单线程:在这种情况下比较容易,因 ...
- JDBC学习总结(二)
1.JDBC的基本应用 1)创建数据库: create database test; use test; 2)创建表: create table student( id int(4) no ...
- Android XML使用的学习记录
1. 注释其中一段代码或是一行,可以采用<!-- -->,示例如下 <!-- <EditText android:layout_width=&quo ...