【题目链接】

  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12406

【题意】

  求最长回文子串。

【思路】

将字符串反向拼接在后,中间用一个没有出现的字符隔开,则问题转化为求新字符串两个特定后缀的lcp,枚举对称点i,对称数为奇的情况对应求lcp(i,n-i),对称数为偶的情况对应求lcp(i,n-i-1)。

如图所示:

两个后缀的lcp可以用Sparse Table算法(倍增)在O(nlogn)时间内求解。

【代码】

 #include<cstdio>
#include<cstring>
#include<iostream>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int maxn = +;
const int maxd = ; int s[maxn];
int sa[maxn],c[maxn],t[maxn],t2[maxn]; void build_sa(int m,int n) {
int i,*x=t,*y=t2;
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(int k=;k<=n;k<<=) {
int p=;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 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]+k]==y[sa[i-]+k]?p-:p++;
if(p>=n) break;
m=p;
}
}
int rank[maxn],height[maxn];
void getHeight(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[j+k]==s[i+k]) k++;
height[rank[i]]=k;
}
}
int A[maxn][maxd];
void RMQ_init(int n) {
for(int i=;i<=n;i++) A[i-][]=height[i];
for(int k=;(<<k)<=n;k++)
for(int i=;(i+(<<k))<=n;i++)
A[i][k]=min(A[i][k-],A[i+(<<(k-))][k-]);
}
int query(int l,int r) {
int k=;
while(<<(k+)<=(r-l+)) k++;
return min(A[l][k],A[r-(<<k)+][k]);
}
int lcp(int a,int b) {
int l=rank[a],r=rank[b];
if(r<l) swap(l,r); l--,r--;
if(r<) return ;
return query(l+,r); //l+1
} int n;
char expr[maxn]; int main() {
while(scanf("%s",expr)==) {
int len=strlen(expr),n=*len+;
for(int i=;i<len;i++)s[i]=expr[i];
s[len]=;
for(int i=;i<len;i++)s[i+len+]=expr[len--i];
s[n]=; build_sa('z'+,n+);
getHeight(n);
RMQ_init(n);
int ans=,front,tmp;
for(int i=;i<n;i++) {
tmp=lcp(i,n-i-);
if(*tmp->ans) { //对称个数为奇数
ans=*tmp-;
front=i-tmp+;
}
tmp=lcp(i,n-i);
if(*tmp>ans) { //对称个数为偶数
ans=*tmp;
front=i-tmp;
}
}
expr[front+ans]='\0';
printf("%s\n",expr+front);
}
return ;
}

UPD:16/4/15

【思路】

  马拉车(Manacher)裸题辣 :)

  不过后缀数组的做法真是神

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
#define rep(a,b,c) for(int a=(b);a>=(c);a--)
using namespace std; typedef long long ll;
const int N = 6e3+; char s[N],a[N];
int p[N],ansl,ansr,ans; void Add(int l,int r)
{
l=l/+,r=r/-;
if(l>r) return ;
if(r-l+>ans) {
ans=r-l+;
ansl=l,ansr=r;
}
} void Manacher()
{
int n=strlen(s+);
int m=*n+;
FOR(i,,n) {
a[i<<]=s[i];
a[i<<|]='#';
}
a[]='+',a[]='#',a[m+]='-';
int mx=,id;
FOR(i,,m) {
if(mx>i) p[i]=min(mx-i,p[*id-i]);
else p[i]=;
while(a[i-p[i]]==a[i+p[i]]) p[i]++;
Add(i-p[i],i+p[i]);
if(p[i]+i>mx) mx=i+p[i],id=i;
}
} int main()
{
while(scanf("%s",s+)==) {
ans=ansl=ansr=;
Manacher();
FOR(i,ansl,ansr) putchar(s[i]);
puts("");
}
return ;
}

Ural1297 Palindrome(后缀数组)的更多相关文章

  1. UVA - 11475 Extend to Palindrome (后缀数组)

    Your task is, given an integer N, to make a palidrome (word that reads the same when you reverse it) ...

  2. 1297. Palindrome ural1297(后缀数组)

    1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB The “U.S. Robots” HQ has just received a ...

  3. URAL 1297 Palindrome 后缀数组

    D - Palindrome Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm ...

  4. URAL - 1297 Palindrome —— 后缀数组 最长回文子串

    题目链接:https://vjudge.net/problem/URAL-1297 1297. Palindrome Time limit: 1.0 secondMemory limit: 64 MB ...

  5. URAL 1297 Palindrome (后缀数组+RMQ)

    题意:给定一个字符串,求一个最长的回回文子串,多解输出第一个. 析:把字符串翻转然后放到后面去,中间用另一个字符隔开,然后枚举每一个回文串的的位置,对第 i 个位置,那么对应着第二个串的最长公共前缀, ...

  6. Ural 1297 Palindrome(Manacher或者后缀数组+RMQ-ST)

    1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The “U.S. Robots” HQ has just received a ...

  7. URAL 1297 Palindrome(后缀数组+ST表)

    [题目链接] http://acm.timus.ru/problem.aspx?num=1297 [题目大意] 求最长回文子串,并输出这个串. [题解] 我们将原串倒置得到一个新的串,加一个拼接符将新 ...

  8. UVA 11475 Extend to Palindrome(后缀数组+ST表)

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...

  9. UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组

    题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...

随机推荐

  1. Unity3D GUI学习之GUI窗口的使用

    GUI还可以定义一个窗口,在窗口里面进行控件的添加: using UnityEngine; using System.Collections; public class getbutton : Mon ...

  2. jetty服务器访问系统的域名

    jetty-env.xml=><Set name="contextPath">/epps-compensation-backend</Set> 这个决 ...

  3. WPF TextSelection获取选中部分内容

    一.简单实例 //TextSelect继承自TextRange TextSelection selection = richTextBox.Selection; //1.获取选中内容 string r ...

  4. while read line无法循环read文件

    while read line 与for循环的区别 例子:要从一个ip列表中获取ip.port,然后ssh ip 到目标机器进行特定的command操作ssh -o StrictHostKeyChec ...

  5. 从零开始学java(猜数字游戏)

    练练手不喜勿喷,看到什么学习什么第一次发博客格式就见见谅.....                                            2016-07-21 19:55:02 imp ...

  6. 使用IDEA,利用SpringMVC框架建立HelloWorld项目

    无论是从头开始学习一门新的语言还是技术,我们的入门都是从HelloWorld开始,也许就是因为这样,我在学习Spring MVC的时候,就有一种偏执,一定要写出一个HelloWorld来.研究了好久, ...

  7. NOIP2012 借教室 Splay初探

    终于把区间操作的Splay搞明白了…… Splay的大致框架是这样的: [代码中的Zig-Zig和Zig-Zag操作其实是可以优化的,实际只需要3次passDown和3次update] templat ...

  8. javascript——事件处理

    <script type="text/javascript"> function EventUtil() { var _self = this; ///添加事件 var ...

  9. spl_autoload_register()和__autoload()

    关于spl_autoload_register()和__autoload() 看两者的用法: //__autoload用法 function __autoload($classname) {     ...

  10. JQUERY 键盘事件

    一 一.首先需要知道的是: 1.keydown()keydown 事件会在键盘按下时触发. 2.keypress()keypress 事件会在敲击按键时触发,我们可以理解为按下并抬起同一个按键. 3. ...