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. html base2

    <html> <body> <h1>My First Web Page</h1> <p id="demo">A Para ...

  2. android性能优化优秀文章

    郭霖最近整理的文章: 合理管理内存 分析编码过程中如何避免过多内存占用,以及如何实现高性能的内存使用. 尽可能使用intentService; 当界面不可见时释放内存; 当内存紧张时释放内存; 避免b ...

  3. plat模板修改记录

    每个栏目显示文章数 homepage.hph 94行 $loop = new WP_Query('post_type=post&showposts=6&category_name=xi ...

  4. 2015十大顶级开源ERP系统点评

    如今,企业资源规划(ERP)和客户关系管理(CRM)系统的必要性已经被各种组织和企业所认可:ERP和CRM能够直接为企业的业务效率和利润做出贡献. 但是随着今天企业商业形态的日趋多样化,互联网新经济的 ...

  5. 解决phpmyadmin上传文件大小限制的配置方法(转)

    phpmyadmin导入SQL文件时涉及到phpmyadmin上传文件大小限制问题,默认phpmyadmin上传文件大小为2M,如果想要 phpmyadmin上传超过2M大文件,就需要修改phpmya ...

  6. 过滤字符串html标签方法

    过滤字符串html标签方法,如果输入的过滤标签为“*”,那么给字符串加上p标签 public static string noTagHtml(string str, string tagname) { ...

  7. Changing a remote's URL

    原文: https://help.github.com/articles/changing-a-remote-s-url/ Changing a remote's URL MAC WINDOWS LI ...

  8. 分析UIWindow

    转载自:http://www.cnblogs.com/YouXianMing/p/3811741.html The UIWindow class defines an object known as ...

  9. Android4.4KitKat支持u盘功能

    Android4.4KitKat支持u盘功能 作者:  发布日期:2014-05-14 23:16:13 我来说两句(0) 0 Tag标签:功能   Android U 盘功能实现和分析 u 盘功能实 ...

  10. PAT 天梯赛 L2-005 集合相似度

    set的应用 题目链接 题解 有点像集合的交并操作,直接利用set进行处理,因为set有去重的功能,而且set是利用红黑树实现的,查找速度快O(logN). 代码如下: #include<cst ...