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. cc2530学习笔记

    case KEY_CHANGE://按键事件 case AF_INCOMING_MSG_CMD://接收数据事件,调用函数AF_DataRequest()接收数据 case ZDO_STATE_CHA ...

  2. java 对象的上转型对象(父类)

    Example5_10.java class 类人猿 { void crySpeak(String s) { System.out.println(s); } } class People exten ...

  3. js 基础对象一

    JavaScript 通常用于操作 HTML 元素. Document元素 每个载入浏览器的 HTML 文档都会成为 Document 对象. Document 对象使我们可以从脚本中对 HTML 页 ...

  4. Maven常用插件配置和使用

    主要介绍Maven的几个常见第三方插件(cobertura.findbugs.source.assembly.插件开发)配置和使用,接Maven介绍 maven本质上是一个插件框架,它的所有工作都交给 ...

  5. Linux批量替换文本,文件夹内所有文本内容

    1.替换文件夹内所有文件匹配的字符串 sed -i "s/旧内容/新内容/g" `grep 旧内容 -rl 文件夹路径` 例如将/var/www/test文件夹下的所有文件内容中的 ...

  6. 打开一个activity,让edittext不获得焦点

      在实际开发中,有的页面用到Edittext控件,这时候进入该页面可能会自动弹出输入法,这么显示不太友好,所以需要设置一下让Edittext默认不自动获取焦点.在网上查资料解决办法如下: 在Edit ...

  7. SystemClock.sleep和Thread.sleep的区别

    在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实 Android平台还提供了一个SystemClock.sleep方 ...

  8. SD卡的控制方法(指令集和控制时序)

    1.SD卡的命令格式: SD卡的指令由6字节(Byte)组成,如下: Byte1:0 1 x x x x x x(命令号,由指令标志定义,如CMD39为100111即16进制0x27,那么完整的CMD ...

  9. 使用VNC远程管理VPS(Centos系统)

    首先安装桌面环境,我选择的是xfce,轻量级桌面,小巧实用不占太多内存,(占用内存方面,xfce<kde,kde<gnome). centos默认源里面没有xfce,首先安装epel源,然 ...

  10. bootstrap-table 表头和内容对不齐解决办法

    偶然机会学习bootstrap,表格利用bootstrap-table实现,使用bootstrap-table过程中,发现了一个非常棘手的问题,在ie浏览器中,表格的表头和内容对不齐,特别是列比较多且 ...