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(后缀数组+最长回文子串)相关推荐

  1. URAL - 1297 Palindrome(后缀数组+RMQ)

    题目链接:点击查看 题目大意:给出一个字符串,求出最长的回文子串 题目分析:如果用以往的方法求,不可避免的都需要枚举所有子串,时间复杂度就已经到达了O(n),而后缀数组可以通过O(n)预处理后得到所有 ...

  2. 最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和...

    最长公共子序列|最长公共子串|最长重复子串|最长不重复子串|最长回文子串|最长递增子序列|最大子数组和 文章作者:Yx.Ac   文章来源:勇幸|Thinking (http://www.ahathi ...

  3. 数组字符串那些经典算法:最大子序列和,最长递增子序列,最长公共子串,最长公共子序列,字符串编辑距离,最长不重复子串,最长回文子串 (转)...

    作者:寒小阳 时间:2013年9月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/11969497. 声明:版权所有,转载请注明出处,谢谢 ...

  4. [Leedcode][JAVA][第5题][最长回文子串][数组][动态规划]

    [问题描述][第5题][最长回文子串][中等] 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000.示例 1:输入: "babad" 输出: & ...

  5. leetcode题库:5.最长回文子串Longest Palindrome string

    题目描述: /** 题目地址:https://leetcode-cn.com/problems/longest-palindromic-substring/description/  * 题目:最长回 ...

  6. day04_ 最长回文子串 / 删除排序数组中的重复项

    day04 5. 最长回文子串 26. 删除排序数组中的重复项 ❗另:java中length,length(),size()区别 5. 最长回文子串 LeetCode链接 给定一个字符串 s,找到 s ...

  7. 统计5个字符串回文个数c语言,第一章 字符串 – 1.5 最长回文子串 - 编程之法:面试和算法心得...

    最长回文子串 题目描述 给定一个字符串,求它的最长回文子串的长度. 分析与解法 最容易想到的办法是枚举所有的子串,分别判断其是否为回文.这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包 ...

  8. 怎么判断一个字符串的最长回文子串是否在头尾_回文自动机入门

    缘起 回文自动机(Palindrome auto machine PAM,有些地方称之为回文树)是回文问题的大杀器~  本文使用一道很简单的题目入门这个精巧的数据结构. hdu 2163 Palind ...

  9. LeetCode:Longest Palindromic Substring 最长回文子串

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

最新文章

  1. 利用window.navigator.userAgent判断当前是否微信内置浏览器
  2. 大数据 互联网架构阶段 Redis(三)redis集群
  3. Linux(centos)的常用基本命令
  4. C++虚函数表和多态
  5. idea插件Lombok
  6. Oracle建立连接的过程分析
  7. 中国科学院计算机研究生面试,19年中科院信工所考研经验分享【初试+复试】
  8. 积分电路与低通滤波器
  9. 主板jrgb是什么_问答:现在的PC主机中有哪些配件支持RGB灯效?
  10. 桌面壁纸 Lively wallpape
  11. Unity3D开发游戏有没有流行的框架
  12. 【转载】深入浅出的讲解傅里叶变换
  13. 【移动安全高级篇】————1、Android沙盘原理与实现
  14. linux需要看门狗喂狗程序,多任务看门狗, 喂狗方法
  15. 判断字符串中是否具有唯一字符
  16. Python实现分层抽样
  17. HMC7044芯片配置总结
  18. 售价80万!高合汽车,流淌法拉第FF的血液?
  19. windows照片查看器提示无法显示图片内存不足
  20. 利用VBA批量删除Excel中的中文/英文/数字或者替换中英文符号

热门文章

  1. 移动端 html5领奖页面,HTML5移动端交互
  2. python循环一段代码_Python循环语句代码详解:while、for、break
  3. python zope 工作流_使用C语言来扩展Python程序和Zope服务器的教程
  4. sql语言快速入门_C语言快速入门——名称可见性
  5. linux spidev 应用_Linux下SPI驱动的移植和应用程序的测试
  6. 迷宫问题 (dfs)
  7. centos7.5 安装apidoc全过程实测
  8. 【Paddle】实践作业——建立模型并测试100张图片
  9. 机器学习笔记——支持向量机
  10. 习题2.7 弹球距离 (15 分)