【ural1297】 Palindrome
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的更多相关文章
- 【Ural1297】Palindrome(后缀数组)
题意:求一个字符串的最长回文子串 n<=1000 思路:这是一道论文题 需要注意的细节: 1.奇偶分类 2.中间的分割符与最后的附加字母都是最小值,但两者不能相同,否则height可能会出现问题 ...
- 【CF932G】Palindrome Partition(回文树,动态规划)
[CF932G]Palindrome Partition(回文树,动态规划) 题面 CF 翻译: 给定一个串,把串分为偶数段 假设分为了\(s1,s2,s3....sk\) 求,满足\(s_1=s_k ...
- 【CF932G】Palindrome Partition 回文自动机
[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_ ...
- 【题解】Palindrome pairs [Codeforces159D]
[题解]Palindrome pairs [Codeforces159D] 传送门:\(Palindrome\) \(pairs\) \([CF159D]\) [题目描述] 给定一个长度为 \(N\) ...
- 【LeetCode】Palindrome Partitioning 解题报告
[题目] Given a string s, partition s such that every substring of the partition is a palindrome. Retur ...
- 【leetcode】Palindrome Number
题目简述: Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could n ...
- 【LeetCode】Palindrome Pairs(336)
1. Description Given a list of unique words. Find all pairs of distinct indices (i, j) in the given ...
- 【leetcode】Palindrome Partitioning II(hard) ☆
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- 【leetcode】 Palindrome Partitioniong (middle) (*^__^*)
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
随机推荐
- pat L2-006. 树的遍历
L2-006. 树的遍历 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历 ...
- Cocos2d 使用控制台打印的方法
1.打开当前项目的win32解决方案. 2.在解决方案管理器的win32文件夹下打开main.cpp 3.增加以下代码: #define USE_WIN32_CONSOLE //以下加到入口函数 #i ...
- 转:全面剖析C#正则表达式
到目前为止,许多的编程语言和工具都包含对正则表达式的支持,当然.NET也不例外,.NET基础类库中包含有一个名称空间和一系列可以充分发挥规则表达式威力的类. 正则表达式的知识可能是不少 ...
- circularprogressbar/smoothprogressbar开源视图使用学习
github地址:https://github.com/castorflex/SmoothProgressBar 多彩圆形进度条和多彩水平进度条 colors.xml 定义变化的颜色内容,用gplus ...
- HDU 2674 N!Again
一开始以为有循环节,输出了前100项发现n>40都是0.因此,水题.... #include<cstdio> ]; ; int main() { a[]=; ; i<=; i+ ...
- Linux添加系统环境变量的两种方法
方法一 export PATH=/usr/local/bin:$PATH 这种方法的PATH 在终端关闭 后就会消失.所以还是建议通过编辑/etc/profile来改PATH 方法二 # vim /e ...
- UI和UE有什么区别呢?
UCD(以用户为中心的设计)UE(用户体验)UI(用户界面)HCI(人机交互)usability(易用性)
- 关于tomcat 成功运行之后内存泄露
在window-preferences 里 搜索 tomcat-jdk 加上以下内容即可 -Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize= ...
- 数的计数(number)
数的计数(number) 题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数n),先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理: (1)不作任何处理: (2)在它的 ...
- DW常用
Dreamweaver代码 基本结构标签: <HTML>,表示该文件为HTML文件 <HEAD>,包含文件的标题,使用的脚本,样式定义等 <TITLE>---< ...