【URAL】1297 Palindrome【字符串--manacher算法】

传送门:Palindrome

题意

求最长回文字符串,在学manacher算法,所以用了manacher,看到网上好多题解使用后缀数组来做的。

思路

manacher算法,参考《ACM国际大学生程序设计竞赛 算法与实现》的板子,一开始我以为板子的manacher算法是错误的,然后上网看题解。

直到我看到 https://blog.csdn.net/u012717411/article/details/53363444 文章,我才知道其实人家是对的,只不过我没理解。

manacher算法在O(N)的时间复杂度内求得了字符串所有子串的最长回文子串的长度。

例如输入

abccba 最终的字符串会变成这样 a#b#c#c#b#a

下标从0开始。

len数组表示以当前位置开始的 最长回文班级,其中# 不考虑。

所以上面例子的len数组如下图所示。

至于manacher算法的原理,我大概理解,但还是不够透彻。可以参考这篇文章。

https://blog.csdn.net/dyx404514/article/details/42061017

AC Code

/*
参考:https://blog.csdn.net/u012717411/article/details/53363444

算法过程: abccba -> a#b#c#c#b#a
下标从0开始。
#位置即(pos&1)==1 的位置 

*/
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e6+5;

void manacher(char str[],int len[],int n) //接口
{
    len[0] = 1;
    for(int i = 1,j = 0; i < (n<<1) - 1; ++ i)
    {
        int p = i >> 1,q = i - p, r = ((j+1) >> 1) + len[j] - 1;
        len[i] = r < q?0:min(r-q+1,len[(j<<1) - i]);
        while(p > len[i] - 1 && q + len[i] < n && str[p - len[i]] == str[q+len[i]]) ++len[i];
        if(q + len[i] - 1 > r) j = i;
    }
}

string longestPalindrome(string s)
{
    int n = s.size();
    /*
    len数组:
    */

    int len[2000];
    char *str = &s[0];
    manacher(str,len,n);//调用接口,得到len[]
    for(int i=0;i<n*2;i++)
    {
        cout<<len[i]<<" ";
    }
    cout<<endl;

    string tmp = "";
    int pos = 0,max_len = 0;
    for(int i = 0; i < (n<<1) - 1; ++ i)
    {
        //以‘#’or字符为中心,串长不一样
        int tmp_len = (i&1)?len[i]<<1:(len[i]<<1)-1;
        //pos记录目标串的中心点,max_len表示目标串的串长(不含#)
        if(tmp_len > max_len) pos = i,max_len = tmp_len;
        //作一个tmp[0..2n-1]的字符串,便于输出
        if(i&1) tmp+="#";
        else tmp+=s[i>>1];
    }
    //# 为中心
    if(pos&1)    //找到要打印的串tmp的起始位置pos和打印长度max_len(便于打印输出)
    {
        max_len = (len[pos] << 2) - 1;
        pos = pos - (len[pos] << 1) + 1;
    }
    else
    {
        max_len = (len[pos] << 2) - 3;
        pos = pos - ((len[pos]-1)<<1);
    }
    string ans = "";
    for(int i = pos,j = 0; j < max_len; ++ j,++ i)
    {
        if(i&1) continue;
        ans+=tmp[i];     //tmp中找到所要打印的字符,链接起来
    }
    return ans;
}

int main()
{
    string s;
    cin>>s;
    cout<<longestPalindrome(s)<<endl;
}

原文地址:https://www.cnblogs.com/shengwang/p/9799903.html

时间: 2024-10-10 05:27:08

【URAL】1297 Palindrome【字符串--manacher算法】的相关文章

Ural 1297 Palindrome(Manacher或者后缀数组+RMQ-ST)

1297. Palindrome Time limit: 1.0 second Memory limit: 64 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»

URAL 1297. Palindrome(输出最长回文子串--后缀数组)

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 ther

URAL1297 Palindrome【manacher算法】

1297. Palindrome Time limit: 1.0 second Memory limit: 64 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".

URAL 1297 Palindrome 后缀数组

1297. Palindrome Time limit: 1.0 second Memory limit: 64 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".

URAL 1297. Palindrome(后缀数组 求最长回文子串)

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1297 1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB The "U.S. Robots" HQ has just received a rather alarming anonymous letter. It states that the agent from the competing ?Robots

URAL 1297. Palindrome(后缀数组求最大回文串)

题目大意:给你一串字符串,让你求出来它存在的最长连续的回文串. 解题思路:先把字符串逆序加到数组中,然后用后缀数组求解.两种方法:1,枚举排名,直接比较rank相同的字符串的位置差是不是len.如果是的话,就记录求解:2,枚举地址,求第i地址与第2*len-i+1的lcp的最大值. PS:需要注意如果多解输出靠前的字符串. 两种写法写在了一起,分别是Del,和Del1函数. 1297. Palindrome Time limit: 1.0 second Memory limit: 64 MB T

后缀数组 POJ 3974 Palindrome &amp;&amp; URAL 1297 Palindrome

题目链接 题意:求给定的字符串的最长回文子串 分析:做法是构造一个新的字符串是原字符串+反转后的原字符串(这样方便求两边回文的后缀的最长前缀),即newS = S + '$' + revS,枚举回文串中心位置,RMQ询问LCP = min (height[rank[l]+1] to height[rank[r]]),注意的是RMQ传入参数最好是后缀的位置,因为它们在树上的顺序未知,且左边还要+1. #include <cstdio> #include <algorithm> #in

查找字符串中的最长回文字符串---Manacher算法

转载:https://www.felix021.com/blog/read.php?2040 首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一个特殊的符号.比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#. 为了进一步减少编码的复杂度,可以在字符串的开始和结尾加入另一个特殊字符这样就不用特殊处理越界问题,比如%#a#b#a#@;(如果是C++,字符串末尾有一个\0,故结尾处不需要添加额为的特殊字符@) 然后用一个数组

ural 1297 Palindrome(Manacher模板题)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud 求最长回文子串. http://acm.timus.ru/problem.aspx?space=1&num=1297 Manacher模板题,复杂度O(n),做这题纯属是为了验一下自己写的模板是否正确. 当然这题也可以用后缀数组来搞 1 #include <iostream> 2 #include <sstream> 3 #include <ios&g