【题目链接】

  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. DIV布局之道三:DIV块的覆盖,DIV层遮盖其他DIV

    DIV布局网页的第三种方式:覆盖.DIV覆盖方式经常应用于网页弹出框的制作,例如在网店系统中,当用户没有登录时,点击购买,系统弹出一个登陆框. 请看代码: HTML部分: XML/HTML Code复 ...

  2. C# List

    命名空间:using System.Collections; class Program {//做个比较 static void Main(string[] args) { //new对象 Cls a ...

  3. SGU 167.I-country

    时间限制:0.75s 空间限制:65M 题意: 在一个n*m(n,m<=15)的网格中,每个格子有一个值,现在从网格中取出k(k<=n*m)个,保证在选中的格子中从任意一个格子去另外的所有 ...

  4. string相关

    1.find相关 string s="abcd"; size_t pos0 = s.find_first_of("dcb");         1    //返 ...

  5. 面试后 follow up letter 分享

    分享一下最近面试外企的follow up letter. Dear Mr. Xu,     Thank you again for the time you and Mr. Guo spent wit ...

  6. easyui tree 判断点击的节点是否还存在子节点

    有些业务需求是要求tree一次性全部加载,有些是需要异步加载的. 如果是一次性全部加载的tree,那怎么判断点击的节点是否还存在子节点? function loadTree(){ $('#tree') ...

  7. smali文件语法参考

    Dalvik opcodes Author: Gabor Paller Vx values in the table denote a Dalvik register. Depending on th ...

  8. 转: Linux C 动态内存分配 malloc及相关内容 .

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

  9. [BZOJ - 2463] [中山市选2009] 谁能赢呢?【“博弈论”】

    题目链接:BZOJ - 2463 题目分析 这道题的题解是,由于两人都采取最优策略,所以最后一定所有格子都会被走到.(Why..表示不懂..哪位神犇可以给我讲一下QAQ) Upd:半群的神犇告诉我,并 ...

  10. Java中接口与实例化

    一.问题引入         前两天学代理模式的时候想到的,接口可不可以new呢?         接口是特殊的抽象类,接口的方法都默认为  public  abstract  的... 抽象的方法不 ...