Ural 1297 Palindrome(后缀数组+最长回文子串)
https://vjudge.net/problem/URAL-1297
题意:
求最长回文子串。
思路:
先将整个字符串反过来写在原字符串后面,中间需要用特殊字符隔开,那么只需要某两个后缀的最长公共前缀。当然,这两个后缀不是让你随便选的,我们需要先确定回文串的中心(那么这儿就需要注意一下奇偶数的情况了,具体可以看一下代码),确定了中心之后,在后面的逆串中,我们也要找到这个中心点的位置,要求的是这两个后缀的公共前缀。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=2000+5; 16 17 int n; 18 char s[maxn]; 19 int sa[maxn],t[maxn],t2[maxn],c[maxn]; 20 int Rank[maxn],height[maxn]; 21 int d[maxn][30]; 22 23 void build_sa(int m) 24 { 25 int *x=t,*y=t2; 26 //基数排序 27 for(int i=0;i<m;i++) c[i]=0; 28 for(int i=0;i<n;i++) c[x[i]=s[i]]++; 29 for(int i=1;i<m;i++) c[i]+=c[i-1]; 30 for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 31 for(int k=1;k<=n;k<<=1) 32 { 33 int p=0; 34 //直接利用sa数组排序第二关键字 35 for(int i=n-k;i<n;i++) y[p++]=i; 36 for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 37 //基数排序第一关键字 38 for(int i=0;i<m;i++) c[i]=0; 39 for(int i=0;i<n;i++) c[x[y[i]]]++; 40 for(int i=1;i<m;i++) c[i]+=c[i-1]; 41 for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 42 //根据sa和y计算新的x数组 43 swap(x,y); 44 p=1; 45 x[sa[0]]=0; 46 for(int i=1;i<n;i++) 47 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 48 if(p>=n) 49 break; 50 m=p; //下次基数排序的最大值 51 } 52 } 53 54 void getHeight(int n) 55 { 56 int i,j,k=0; 57 for(i=1;i<=n;i++) Rank[sa[i]]=i; 58 for(i=0;i<n;i++) 59 { 60 if(k) k--; 61 int j=sa[Rank[i]-1]; 62 while(s[i+k]==s[j+k]) k++; 63 height[Rank[i]]=k; 64 } 65 } 66 67 void RMQ(int n) 68 { 69 for(int i=1;i<=n;i++) d[i-1][0]=height[i]; 70 for(int j=1;(1<<j)<=n;j++) 71 for(int i=0;i+(1<<j)-1<n;i++) 72 d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]); 73 } 74 75 int query(int L, int R) 76 { 77 int k=0; 78 while((1<<(k+1))<=R-L+1) k++; 79 return min(d[L][k],d[R-(1<<k)+1][k]); 80 } 81 82 int LCP(int a, int b) 83 { 84 int x=Rank[a],y=Rank[b]; 85 if(x>y) swap(x,y); 86 x--; y--; 87 if(y<0) return 0; 88 return query(x+1,y); 89 } 90 91 int main() 92 { 93 //freopen("in.txt","r",stdin); 94 while(~scanf("%s",s)) 95 { 96 int len = strlen(s); 97 s[len]='1'; 98 for(int i=0;i<len;i++) s[i+len+1]=s[len-1-i]; 99 s[2*len+1]='0'; //这儿后面的数要加的不一样,一开始两个都加了'0'... 100 n=2*len+2; 101 build_sa(128); 102 getHeight(n-1); 103 RMQ(n-1); 104 int ans=0, tmp, start; 105 for(int i=0;i<len;i++) 106 { 107 tmp=LCP(i,n-i-2); //长度为奇数的情况 108 if(2*tmp-1>ans) 109 { 110 ans=2*tmp-1; 111 start=i-tmp+1; 112 } 113 tmp=LCP(i,n-i-1); //长度为偶数的情况 114 if(2*tmp>ans) 115 { 116 ans=2*tmp; 117 start=i-tmp; 118 } 119 } 120 for(int i=start;i<start+ans;i++) 121 printf("%c",s[i]); 122 printf("\n"); 123 } 124 return 0; 125 }
转载于:https://www.cnblogs.com/zyb993963526/p/7580290.html
Ural 1297 Palindrome(后缀数组+最长回文子串)相关推荐
- URAL - 1297 Palindrome(后缀数组+RMQ)
题目链接:点击查看 题目大意:给出一个字符串,求出最长的回文子串 题目分析:如果用以往的方法求,不可避免的都需要枚举所有子串,时间复杂度就已经到达了O(n),而后缀数组可以通过O(n)预处理后得到所有 ...
- 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...
最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和 文章作者:Yx.Ac 文章来源:勇幸|Thinking (http://www.ahathi ...
- 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...
作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...
- [Leedcode][JAVA][第5题][最长回文子串][数组][动态规划]
[问题描述][第5题][最长回文子串][中等] 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000.示例 1:输入: "babad" 输出: & ...
- leetcode题库:5.最长回文子串Longest Palindrome string
题目描述: /** 题目地址:https://leetcode-cn.com/problems/longest-palindromic-substring/description/ * 题目:最长回 ...
- day04_ 最长回文子串 / 删除排序数组中的重复项
day04 5. 最长回文子串 26. 删除排序数组中的重复项 ❗另:java中length,length(),size()区别 5. 最长回文子串 LeetCode链接 给定一个字符串 s,找到 s ...
- 统计5个字符串回文个数c语言,第一章 字符串 – 1.5 最长回文子串 - 编程之法:面试和算法心得...
最长回文子串 题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包 ...
- 怎么判断一个字符串的最长回文子串是否在头尾_回文自动机入门
缘起 回文自动机(Palindrome auto machine PAM,有些地方称之为回文树)是回文问题的大杀器~ 本文使用一道很简单的题目入门这个精巧的数据结构. hdu 2163 Palind ...
- LeetCode:Longest Palindromic Substring 最长回文子串
Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...
最新文章
- 利用window.navigator.userAgent判断当前是否微信内置浏览器
- 大数据 互联网架构阶段 Redis(三)redis集群
- Linux(centos)的常用基本命令
- C++虚函数表和多态
- idea插件Lombok
- Oracle建立连接的过程分析
- 中国科学院计算机研究生面试,19年中科院信工所考研经验分享【初试+复试】
- 积分电路与低通滤波器
- 主板jrgb是什么_问答:现在的PC主机中有哪些配件支持RGB灯效?
- 桌面壁纸 Lively wallpape
- Unity3D开发游戏有没有流行的框架
- 【转载】深入浅出的讲解傅里叶变换
- 【移动安全高级篇】————1、Android沙盘原理与实现
- linux需要看门狗喂狗程序,多任务看门狗, 喂狗方法
- 判断字符串中是否具有唯一字符
- Python实现分层抽样
- HMC7044芯片配置总结
- 售价80万!高合汽车,流淌法拉第FF的血液?
- windows照片查看器提示无法显示图片内存不足
- 利用VBA批量删除Excel中的中文/英文/数字或者替换中英文符号
热门文章
- 移动端 html5领奖页面,HTML5移动端交互
- python循环一段代码_Python循环语句代码详解:while、for、break
- python zope 工作流_使用C语言来扩展Python程序和Zope服务器的教程
- sql语言快速入门_C语言快速入门——名称可见性
- linux spidev 应用_Linux下SPI驱动的移植和应用程序的测试
- 迷宫问题 (dfs)
- centos7.5 安装apidoc全过程实测
- 【Paddle】实践作业——建立模型并测试100张图片
- 机器学习笔记——支持向量机
- 习题2.7 弹球距离 (15 分)