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. 微软企业库3.1DIY编译使用(数据库连接符写在企业库DLL里)

    1.在winform项目app.config文件中去掉"PublicKeyToken=b03f5f7f11d50a3a"(不然无法加载使用新编译的企业库DLL文件) 2.在企业库所 ...

  2. HDU 5739 Fantasia

    可以将这个图转换成森林来进行树形dp求解.看了这篇具体教学才会的:http://www.cnblogs.com/WABoss/p/5696926.html 大致思路:求解一下点双连通分量(Tarjan ...

  3. 一个appium 博客

    http://www.cnblogs.com/tobecrazy/category/699177.html appium Java控制Appium server start/stop 摘要: 相信很多 ...

  4. HDU 2475 BOX 动态树 Link-Cut Tree

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem De ...

  5. ubuntu 14.0.4下安装有道字典

    一,下载安装包地址:http://codown.youdao.com/cidian/linux/youdao-dict_1.0.2~ubuntu_i386.deb http://codown.youd ...

  6. FFmpeg的Android平台移植—编译篇

    摘要:本文主要介绍将FFmpeg音视频编解码库移植到Android平台上的编译和基本测试过程. 环境准备: ubuntu-12.04.5 android-ndk64-r10-linux-x86_64. ...

  7. mysql慢查询问题

    [问题现象] 使用sphinx支持倒排索引,但sphinx从mysql查询源数据的时候,查询的记录数才几万条,但查询的速度非常慢,大概要4~5分钟左右 [处理过程] 1)explain 首先怀疑索引没 ...

  8. zf-关于平台的用户名密码的设置

    比如说安徽桐城的用户名密码在哪张表里设置 桐城市人民统一电子政务平台是http://localhost:8088/tc/ptzwfw.action 这个链接 在zwfw_tc 数据库的 PT_LOGI ...

  9. Android调用第三方so

    http://blog.csdn.net/jiuyueguang/article/details/9450597 ubuntu下整合eclipse和javah生成jni头文件开发android的nat ...

  10. 转:从web三层架构解析软件测试内容

    B/S架构的系统,都会使用如下的基础软件架构: 数据访问层:实现对数据的访问功能,如增加.删除.修改.查询数据. 业务逻辑层:实现业务的具体逻辑功能,如学生入学.退学.成绩管理等. 页面显示层:将业务 ...