后缀数组 - 求最长回文子串 + 模板题 --- ural 1297

简介: 1297. Palindrome Time Limit: 1.0 secondMemory Limit: 16 MB The “U.S. Robots” HQ has just received a rather alarming anonymous letter.

 

1297. Palindrome

Time Limit: 1.0 second
Memory Limit: 16 MB
The “U.S. Robots” HQ has just received a rather alarming anonymous letter. It states that the agent from the competing «Robots Unlimited» has infiltrated into “U.S. Robotics”. «U.S. Robots» security service would have already started an undercover operation to establish the agent’s identity, but, fortunately, the letter describes communication channel the agent uses. He will publish articles containing stolen data to the “Solaris” almanac. Obviously, he will obfuscate the data, so “Robots Unlimited” will have to use a special descrambler (“Robots Unlimited” part number NPRx8086, specifications are kept secret).
Having read the letter, the “U.S. Robots” president recalled having hired the “Robots Unlimited” ex-employee John Pupkin. President knows he can trust John, because John is still angry at being mistreated by “Robots Unlimited”. Unfortunately, he was fired just before his team has finished work on the NPRx8086 design.
So, the president has assigned the task of agent’s message interception to John. At first, John felt rather embarrassed, because revealing the hidden message isn’t any easier than finding a needle in a haystack. However, after he struggled the problem for a while, he remembered that the design of NPRx8086 was still incomplete. “Robots Unlimited” fired John when he was working on a specific module, the text direction detector. Nobody else could finish that module, so the descrambler will choose the text scanning direction at random. To ensure the correct descrambling of the message by NPRx8086, agent must encode the information in such a way that the resulting secret message reads the same both forwards and backwards.
In addition, it is reasonable to assume that the agent will be sending a very long message, so John has simply to find the longest message satisfying the mentioned property.
Your task is to help John Pupkin by writing a program to find the secret message in the text of a given article. As NPRx8086 ignores white spaces and punctuation marks, John will remove them from the text before feeding it into the program.

Input

The input consists of a single line, which contains a string of Latin alphabet letters (no other characters will appear in the string). String length will not exceed 1000 characters.

Output

The longest substring with mentioned property. If there are several such strings you should output the first of them.

Sample

input
ThesampletextthatcouldbereadedthesameinbothordersArozaupalanalapuazorA
output
ArozaupalanalapuazorA 
 

 

Mean: 

 给你一个字符串,让你输出字符串的最长回文子串。

analyse:

求最长回文串有很多方法,最经典的莫过于Manacher算法,时间复杂度O(n)。

这里就主要介绍一下用后缀数组的方法。

用后缀数组怎么求回文串呢?

原理和上一篇求最长公共子序列一样,我们把s1反转后接到s1后面得到S串,那么s1的最长回文串必定存在于S中,我们只需要求一下S的height数组,然后寻找来自于不同的两个串的height[i]的最大值,然后记录一下开始位置和长度,最后输出即可。

Time complexity:O(nlogn)

 

Source code:

 Suffix Arrays:

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-05-09-21.22
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;
const int MAXN = 2015;
//以下为倍增算法求后缀数组
int wa [ MAXN ], wb [ MAXN ], wv [ MAXN ], Ws [ MAXN ];
int cmp( int * r , int a , int b , int l)
{ return r [ a ] == r [b ] && r [ a + l ] == r [b + l ];}
/**< 传入参数:str,sa,len+1,ASCII_MAX+1 */
void da( const char * r , int * sa , int n , int m)
{
      int i , j ,p , * x = wa , * y = wb , * t;
      for( i = 0; i < m; i ++) Ws [ i ] = 0;
      for( i = 0; i <n; i ++) Ws [ x [ i ] = r [ i ]] ++;
      for( i = 1; i < m; i ++) Ws [ i ] += Ws [ i - 1 ];
      for( i =n - 1; i >= 0; i --) sa [ -- Ws [ x [ i ]]] = i;
      for( j = 1 ,p = 1; p <n; j *= 2 , m =p)
      {
            for(p = 0 , i =n - j; i <n; i ++) y [p ++ ] = i;
            for( i = 0; i <n; i ++) if( sa [ i ] >= j) y [p ++ ] = sa [ i ] - j;
            for( i = 0; i <n; i ++) wv [ i ] = x [ y [ i ]];
            for( i = 0; i < m; i ++) Ws [ i ] = 0;
            for( i = 0; i <n; i ++) Ws [ wv [ i ]] ++;
            for( i = 1; i < m; i ++) Ws [ i ] += Ws [ i - 1 ];
            for( i =n - 1; i >= 0; i --) sa [ -- Ws [ wv [ i ]]] = y [ i ];
            for( t = x , x = y , y = t ,p = 1 , x [ sa [ 0 ]] = 0 , i = 1; i <n; i ++)
                  x [ sa [ i ]] = cmp( y , sa [ i - 1 ], sa [ i ], j) ?p - 1 :p ++;
      }
      return;
}
int sa [ MAXN ], Rank [ MAXN ], height [ MAXN ];
/**< str,sa,len */
void calheight( const char * r , int * sa , int n)
{
      int i , j , k = 0;
      for( i = 1; i <=n; i ++) Rank [ sa [ i ]] = i;
      for( i = 0; i <n; height [ Rank [ i ++ ]] = k)
            for( k ? k --: 0 , j = sa [ Rank [ i ] - 1 ]; r [ i + k ] == r [ j + k ]; k ++);
      // Unified
      for( int i =n; i >= 1; -- i) ++ sa [ i ], Rank [ i ] = Rank [ i - 1 ];
}

char s1 [ MAXN ], s2 [ MAXN ];
int main()
{
      while( ~ scanf( "%s" , s1))
      {
            int l1 = strlen( s1);
            strcat( s1 , "{");
            strcpy( s2 , s1);
            for( int i = 0; i < l1; ++ i) s1 [ i + l1 + 1 ] = s2 [ l1 - i - 1 ];
            int len = strlen( s1);
            da( s1 , sa , len + 1 , 130);
            calheight( s1 , sa , len);
            int sta = 0 , maxLen = 1 , l , r;
            for( int i = 1; i <= len; ++ i)
            {
                  l = min( sa [ i ] - 1 , sa [ i - 1 ] - 1);
                  r = max( sa [ i ] - 1 , sa [ i - 1 ] - 1);
                  if(( l < l1 && r > l1) && ( len - r == l + height [ i ]))
                  {
                        if( height [ i ] > maxLen)
                              maxLen = height [ i ], sta = l;
                        else if( height [ i ] == maxLen)
                              sta = min( sta , l);
                  }
            }
            for( int i = sta , j = 0; j < maxLen; ++ i , ++ j)
                printf( "%c" , s1 [ i ]);
            puts( "");
      }
      return 0;
}

 

 Manacher:

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-09-12-15.41
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define max(a,b) (a>b?a:b)
using namespace std;
typedef long long( LL);
typedef unsigned long long( ULL);
const double eps( 1e-8);

/** O(n)内求出所有回文串
*原串 :abaaba
*Ma串 :.,a,b,a,a,b,a,
*Mp[i]:Ma串中,以字符Ma[i]为中心的最长回文子串的半径长度(包括Ma[i],也就是把回文串对折后的长度).
****经过对原串扩展处理后,将奇数串的情况也合并到了偶数的情况(不需要考虑奇数串)
*/
const int MAXN = 1050;
char Ma [ MAXN * 2 ],s [ MAXN ];
int Mp [ MAXN * 2 ], Mplen;
void Manacher( char s [], int len)
{
      int le = 0;
      Ma [ le ++ ] = '.';
      Ma [ le ++ ] = ',';
      for( int i = 0; i < len; ++ i)
      {
            Ma [ le ++ ] =s [ i ];
            Ma [ le ++ ] = ',';
      }
      Mplen = le;
      Ma [ le ] = 0;
      int pnow = 0 , pid = 0;
      for( int i = 1; i < le; ++ i)
      {
            if( pnow > i)
                  Mp [ i ] = min( Mp [ 2 * pid - i ], pnow - i);
            else
                  Mp [ i ] = 1;
            for(; Ma [ i - Mp [ i ]] == Ma [ i + Mp [ i ]]; ++ Mp [ i ]);
            if( i + Mp [ i ] > pnow)
            {
                  pnow = i + Mp [ i ];
                  pid = i;
            }
      }
}

int main()
{
      ios_base :: sync_with_stdio( false);
      cin . tie( 0);
      while( ~ scanf( "%s" ,s))
      {
            Manacher(s , strlen(s));
            int maxLen = 1 , idx = 0;
            for( int i = 0; i < Mplen; ++ i)
            {
                  if( Mp [ i ] > maxLen)
                        maxLen = Mp [ i ], idx = i;
            }
            for( int i =( idx - maxLen + 1) / 2 , j = 0; j < maxLen - 1; ++ i , ++ j)
                  printf( "%c" ,s [ i ]);
            puts( "");
//            cout<<maxLen-1<<endl;
      }
      return 0;
}

 

目录
相关文章
|
XML Web App开发 SQL
一文带你了解网页的灰色效果是如何实现的
一文带你了解网页的灰色效果是如何实现的
409 40
|
新零售 人工智能
阿里巴巴联合汉仪重磅推出五款人工智能字体:汉仪天真体、英雄体等
众所周知传统做字的人力成本非常之高,如果全靠人类设计师来完成,一套标准字库从设计到完成需要一年多的时间。
13467 0
|
应用服务中间件 Linux nginx
|
传感器 机器学习/深度学习 人工智能
光子集成电路:光子学与电子学的结合
【10月更文挑战第18天】光子集成电路(PIC)结合了光子学与电子学的优势,利用光子作为信息传输和处理的载体,具备高速传输、大带宽、低功耗和高集成度等特点。本文介绍其基本原理、技术优势及在高速光通信、光计算、传感器和激光雷达等领域的应用前景,展望未来发展趋势与挑战。
|
9月前
|
机器学习/深度学习 自然语言处理 安全
DeepSeek-R1 体验评测报告:智能推理新高度
DeepSeek-R1 体验评测报告:智能推理新高度
709 7
DeepSeek-R1 体验评测报告:智能推理新高度
|
10月前
|
弹性计算 运维 监控
云资源运维与管理体验分享
作为一名开发工程师,我分享了在云资源运维与管理中的体验。健康状态功能实时监控ECS实例的关键指标,如CPU负载、内存使用率等,及时预警并解决问题,确保业务连续性。诊断功能通过日志分析和性能剖析快速定位复杂问题,提升故障处理效率。建议优化包括自定义告警阈值、多维度数据展示、自动化修复、集成更多日志源及建立用户反馈机制。这些功能显著提升了系统的稳定性和运维效率。
171 4
|
量子技术
量子计算与教育:培养下一代量子科学家
在21世纪科技浪潮中,量子计算正从理论走向实践,深刻影响科学研究、工业制造、信息安全等领域。本文探讨量子计算与教育的结合,旨在培养具备量子思维和创新能力的下一代科学家,为未来科技创新奠定基础。通过课程革新、跨学科教育、实践平台搭建及国际化视野培养等策略,激发学生兴趣,提供丰富教育资源,强化实践与团队协作,推动量子科学的发展。
|
物联网 5G 数据处理
|
算法 安全 固态存储
删除的文件怎么找回?删除文件恢复全面指南
我们常常在日常生活或工作中不小心删除了重要文件,这样的情况可能瞬间让人感到无助。不过,数据恢复技术已相当成熟,我们可以通过多种方法来找回误删的文件。下面我们将从简单到复杂逐步讲解找回删除文件的方法,希望可以帮助大家在意外发生时及时找回丢失的文件。
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
744 3