http://acm.timus.ru/problem.aspx?space=1&num=1297 (题目链接)

题意

  求最长回文子串

Solution

  后缀数组论文题

  穷举每一位,然后计算以这个字符为中心的最长回文子串。注意这里要分两种情况,一是回文子串的长度为奇数,二是长度为偶数。两种情况都可以转化为 求一个后缀和一个反过来写的后缀的最长公共前缀。具体的做法是:将整个字符串反过来写在原字符串后面,中间用一个特殊的字符隔开。这样就把问题变为了求这个新的字符串的某两个后缀的最长公共前缀。如图:

  感觉后缀数组好像就两个比较有用的操作,一是对height分组,二是将两个串相接并用分隔符隔开。

细节

  想清楚再写,ST表调了半天。。

代码

// ural1297
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=2010;
int rank[maxn],sa[maxn],height[maxn];
int bin[30],st[maxn][30],Log[maxn];
char s[maxn]; namespace Suffix {
int wa[maxn],wb[maxn],ww[maxn];
bool cmp(int *r,int a,int b,int l) {
return r[a]==r[b] && r[a+l]==r[b+l];
}
void da(char *r,int *sa,int n,int m) {
int i,j,p,*x=wa,*y=wb;
for (i=0;i<=m;i++) ww[i]=0;
for (i=1;i<=n;i++) ww[x[i]=r[i]]++;
for (i=1;i<=m;i++) ww[i]+=ww[i-1];
for (i=n;i>=1;i--) sa[ww[x[i]]--]=i;
for (p=0,j=1;p<n;j*=2,m=p) {
for (p=0,i=n-j+1;i<=n;i++) y[++p]=i;
for (i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j;
for (i=0;i<=m;i++) ww[i]=0;
for (i=1;i<=n;i++) ww[x[y[i]]]++;
for (i=1;i<=m;i++) ww[i]+=ww[i-1];
for (i=n;i>=1;i--) sa[ww[x[y[i]]]--]=y[i];
for (swap(x,y),p=x[sa[1]]=1,i=2;i<=n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p : ++p;
}
}
void calheight(char *r,int *sa,int n) {
for (int i=1;i<=n;i++) rank[sa[i]]=i;
for (int k=0,i=1;i<=n;i++) {
if (k) k--;
int j=sa[rank[i]-1];
while (r[i+k]==r[j+k]) k++;
height[rank[i]]=k;
}
}
}
int query(int x,int y) {
if (x>y) swap(x,y);x++;
int k=Log[y-x+1];
return min(st[x][k],st[y-bin[k]+1][k]);
}
int main() {
bin[0]=1;for (int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
scanf("%s",s+1);
int n=strlen(s+1);
s[n+1]='#';
for (int i=1;i<=n;i++) s[n+i+1]=s[n-i+1];
n+=n+1;
Suffix::da(s,sa,n,300);
Suffix::calheight(s,sa,n);
for (int i=1;i<=n;i++) st[i][0]=height[i];
for (int j=1;j<=20;j++)
for (int i=1;i+bin[j]<=n+1;i++)
st[i][j]=min(st[i][j-1],st[i+bin[j-1]][j-1]);
for (int i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
int l=1,r=1;
for (int i=1;i<=n/2;i++) {
int l1=query(rank[i],rank[n-i+1]);
int l2=query(rank[i+1],rank[n-i+1]);
if (r-l+1<l1*2-1) l=i-l1+1,r=i+l1-1;
if (r-l+1<l2*2) l=i-l2+1,r=i+l2;
}
for (int i=l;i<=r;i++) printf("%c",s[i]);
return 0;
}

Solution

  manacher板子题

细节

  注意数组开两倍,以及刚开始的开始符。下标要想清楚。

代码

// ural1297
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1ll<<60
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=100010;
char s[maxn],st[maxn];
int p[maxn],n; int Manachar() {
int len=2;
st[1]='$';st[2]='#';
for (int i=1;i<=n;i++) {
st[++len]=s[i];
st[++len]='#';
}
st[++len]='\0';
int mx=0,pos=0,id;
for (int i=1;i<=len;i++) {
if (i<mx) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while (st[i-p[i]]==st[i+p[i]]) p[i]++;
if (mx<i+p[i]) id=i,mx=i+p[i];
if (p[pos]<p[i]) pos=i;
}
return pos;
}
int main() {
scanf("%s",s+1);
n=strlen(s+1);
int k=Manachar();
for (int i=k-p[k]+1;i<=k+p[k]-1;i++) if (st[i]!='#') printf("%c",st[i]);
return 0;
}

【ural1297】 Palindrome的更多相关文章

  1. 【Ural1297】Palindrome(后缀数组)

    题意:求一个字符串的最长回文子串 n<=1000 思路:这是一道论文题 需要注意的细节: 1.奇偶分类 2.中间的分割符与最后的附加字母都是最小值,但两者不能相同,否则height可能会出现问题 ...

  2. 【CF932G】Palindrome Partition(回文树,动态规划)

    [CF932G]Palindrome Partition(回文树,动态规划) 题面 CF 翻译: 给定一个串,把串分为偶数段 假设分为了\(s1,s2,s3....sk\) 求,满足\(s_1=s_k ...

  3. 【CF932G】Palindrome Partition 回文自动机

    [CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_ ...

  4. 【题解】Palindrome pairs [Codeforces159D]

    [题解]Palindrome pairs [Codeforces159D] 传送门:\(Palindrome\) \(pairs\) \([CF159D]\) [题目描述] 给定一个长度为 \(N\) ...

  5. 【LeetCode】Palindrome Partitioning 解题报告

    [题目] Given a string s, partition s such that every substring of the partition is a palindrome. Retur ...

  6. 【leetcode】Palindrome Number

    题目简述: Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could n ...

  7. 【LeetCode】Palindrome Pairs(336)

    1. Description Given a list of unique words. Find all pairs of distinct indices (i, j) in the given ...

  8. 【leetcode】Palindrome Partitioning II(hard) ☆

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  9. 【leetcode】 Palindrome Partitioniong (middle) (*^__^*)

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...

随机推荐

  1. HDU1518:Square(DFS)

    Square Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submi ...

  2. hadoop yarn 易理解

    Hadoop 和 MRv1 简单介绍 Hadoop 集群可从单一节点(其中所有 Hadoop 实体都在同一个节点上运行)扩展到数千个节点(其中的功能分散在各个节点之间,以增加并行处理活动).图 1 演 ...

  3. IE8浏览器兼容问题总结

    IE8+兼容经验小结 January 15, 2014 本文分享下我在项目中积累的IE8+兼容性问题的解决方法.根据我的实践经验,如果你在写HTML/CSS时候是按照W3C推荐的方式写的,然后下面的几 ...

  4. Oracle Sql优化之Rownum的使用

    1.rownum:rownum是一个伪列,需要在数据取出来后,rownum才会有值,因此在分页查找时,需要进行嵌套查询. select sal,ename from (select rownum as ...

  5. Android Studio开发环境的配置

    为了使开发人员与时俱进, 在这里给大家讲解一下Android Studio的安装步骤及设置. 使用的是Android的最新版本,0.4.2版本,Android Studio可以脱离Eclipse单独运 ...

  6. .NET中公共变量与属性的区别

    在我们的程序中经常会出现以下的代码:  如:     成员变量     public   string   Name;     或者用属性     private   string   name    ...

  7. jquery页面滑到底部加载更多

    $(window).scroll(function(){ var _scrolltop = $('body').scrollTop();if(_scrolltop+_winHeight>_doc ...

  8. 盖房子(house)

    盖房子(house) 题目描述 FJ最近得到了面积为n*m的一大块土地,他想在这块土地上建造一所房子,这个房子必须膏形的.但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵).这些瑕疵十 ...

  9. linux 备份系统

    切换到root用户 切换到根目录 tar cvpzf backup.tgz --exclude=/proc --exclude=/lost+found --exclude=/backup.tgz -- ...

  10. dedecms 的这个dede:arclist里怎么调用全局变量?

    将{dede:global.cfg_templets_skin/} 写为 [field:global.cfg_templets_skin/] 即可.