【题目链接】

  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. 获取Android studio中的SHA1

    因为想要弄一下百度地图. 然后要申请一个key. 需要SHA1. 按window键 +R 输入cmd 进入C:\Users\Administrator路径 输入cd .android,进行.andro ...

  2. Android Animation学习 实现 IOS 滤镜退出动画

    IOS的用户体验做的很好,其中一点很重要的地方就是动画效果. 最近在学习Android的Animation,简单实现了一个IOS相机滤镜退出的动画: 布局文件:activity_animation_d ...

  3. Wireshark提示没有一个可以抓包的接口

    这是由于win下默认NPF服务是关闭的,需要以管理员的身份开启这个服务 Windows上安装wireshark时,会遇到NPF驱动无法启动的情况,一般如果采用管理员的方式就可以正常启动,或者是将NPF ...

  4. CAEmitterLayer

    -(void)createFireworks{ CAEmitterLayer *fireworks = [CAEmitterLayer layer]; fireworks.emitterPositio ...

  5. NSJSONSerialization-JSON数据与NSDictionary和NSArray之间的转化

    转载▼     在iOS  5 中,苹果引入了一个解析JSON串的NSJSONSerialization类. 通过该类,我们可以完成JSON数据与NSDictionary和NSArray之间的转化. ...

  6. jQuery Callback 方法

    Callback 函数在当前动画 100% 完成之后执行. jQuery 动画的问题 许多 jQuery 函数涉及动画.这些函数也许会将 speed 或 duration 作为可选参数. 例子:$(& ...

  7. [转]Delphi执行CMD命令

    今天看到有人在问用代码执行CMD命令的问题,就总结一下用法,也算做个备忘. Delphi中,执行命令或者运行一个程序有2个函数,一个是winexec,一个是shellexecute.这两个大家应该都见 ...

  8. style currentStyle getComputedStyle的区别和用法

    先介绍下层叠样式表的三种形式: 1.内联样式,在html标签中style属性设置. <p style="color:#f90">内联样式</p> 2.嵌入样 ...

  9. WampServer修改端口及菜单Localhost

    一.修改Apache端口 1.在界面中选Apache,弹出隐藏菜单选项,打开配置文件httpd.conf: 2.找到 Listen 80: 3.将 80 改成 8080(当然自己也可以设定别的不使用的 ...

  10. 【BZOJ3673】【可持久化并查集】可持久化并查集 by zky

    Description n个集合 m个操作操作:1 a b 合并a,b所在集合2 k 回到第k次操作之后的状态(查询算作操作)3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 0<n ...