题意:就是让你求一个字符串中的最长回文,如果有多个长度相等的最长回文,那就输出第一个最长回文。

思路:这是后缀数组的一种常见的应用,首先把原始字符串倒转过来,然后接在原始字符串的后面,中间用一个不可能出现的字符隔开。然后就用到后缀数组的性质了,

我们枚举每一个原始字符串中的字符以它为中心(分为奇数和偶数两种情况)进行查找,比如对于下标为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)的更多相关文章

  1. URAL 1297 后缀数组:求最长回文子串

    思路:这题下午搞了然后一直WA,后面就看了Discuss,里面有个数组:ABCDEFDCBA,这个我输出ABCD,所以错了. 然后才知道自己写的后缀数组对这个回文子串有bug,然后就不知道怎么改了. ...

  2. URAL - 1297 后缀数组的做法 LCP应用

    题意:求最长回文子串 这种有专门的O(n)套板子算法,但作为练习还是用后缀数组来解吧 只需把相同的另一个串反接(中间用一个足够小且未出现的字符衔接),然后枚举回文串的中点,不断求解该点往前和往后计算的 ...

  3. ural 1297 后缀数组 最长回文子串

    https://vjudge.net/problem/URAL-1297 题意: 给出一个字符串求最长回文子串 代码: //论文题,把字符串反过来复制一遍到后边,中间用一个没出现的字符隔开,然后就是枚 ...

  4. URAL 1297 后缀数组+线段树

    思路: 论文题--*n 倒过来接上 分奇偶讨论 求LCP 搞棵线段树即可 //By SiriusRen #include <cstdio> #include <cstring> ...

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

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

  6. POJ 3693 后缀数组+RMQ

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

  7. 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 ...

  8. HDU2459 后缀数组+RMQ

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

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

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

随机推荐

  1. [C++]虚函数-同名访问

    首先来看一下派生类和基类成员同名事的处理规则: 派生类内定义了一个与基类同名的成员,该现象称为同名覆盖,此时,无论派生类内部成员函数还是派生类的对象访问同名成员,如果未加任何特殊标识,则访问派生类中重 ...

  2. ****Git 常用命令和使用思维导图

    Git 是一个很强大的分布式版本控制系统.它不但适用于管理大型开源软件的源代码,管理私人的文档和源代码也有很多优势. 本来想着只把最有用.最常用的 Git 命令记下来,但是总觉得这个也挺有用.那个也用 ...

  3. django --fields.E304 错误解决方案

    今天在同一个表里,有多个不同的用户集时出现. fields.E304: Field name <field name> clashes with accessor for <fiel ...

  4. 深入浅出Java并发包—锁机制(二)

    接上文<深入浅出Java并发包—锁机制(一)  >  2.Sync.FairSync.TryAcquire(公平锁) 我们直接来看代码 protected final boolean tr ...

  5. XML中如何使用schema

    Schema简介 DTD的语法相当复杂,并且它不符合XML文件的标准,自成一个体系,W3C定义的Schema用来代替DTD. chema相对于DTD的明显好处是XML Schema文档本身也是XML文 ...

  6. 李洪强iOS开发之OC[015]#pragma mark的使用

    // //  main.m //  14 - #pragma mark的使用 // //  Created by vic fan on 16/7/10. //  Copyright © 2016年 李 ...

  7. 【Linux高频命令专题(22)】gzip

    概述 减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅 ...

  8. 1、Singleton 单件(创建模式)

    一.Singleton模式主要应用在一些特殊的类,在整个系统运行中,有且仅有一个实例的场景 二.Singleton模式分为单线程与多线程情况,当然多线程一样适应单线程 单线程:在这种情况下比较容易,因 ...

  9. JDBC学习总结(二)

    1.JDBC的基本应用 1)创建数据库: create database test;   use test; 2)创建表: create table student(     id int(4) no ...

  10. Android XML使用的学习记录

    1. 注释其中一段代码或是一行,可以采用<!-- -->,示例如下 <!--       <EditText         android:layout_width=&quo ...