查找字符串中的最长回文问题评述

class Solution {
public:
  string longestPalindrome(string s) {
    string post;
    post.resize(s.size()*2+2);
    post[0] = '&';
    for (int i = 0;i<s.size();i++){
      post[2*i + 1] = s[i];
      post[2*i + 2] ='#';
    }
    post[s.size()*2] = '#';
    post[s.size()*2+1]='$';
    cout << "post:" << post.length() << endl;

    vector<int> rad;
    rad.resize(post.size());
    rad[0] = 0;
    int max_rad = 0;
    int center = 1;
    int j = 0;
    for (int i = 1; i < post.length() - 1; i) {
      while ( post[i + j] == post[i - j]) {
        j++;
      }
      rad[i] = j-1;
      //cout << i << "," << rad[i];
      if (rad[i]> max_rad) {
        center = i;
        max_rad = rad[i];
      }
      int k;
      for (k = 1;k < j && rad[i-k] != rad[i] - k;k++){
        rad[i+k] = min(rad[i-k], rad[i] - k);
        //cout << i+k << "," << rad[i+k];
      }
      i = i + k;
      j = max(0, j - k);
    }
    string res;
    if (center%2 == 1) {
      res = s.substr(center/2 - max_rad/2, max_rad/2*2+1);
    } else {
      res = s.substr((center + 1)/2- (max_rad+1)/2, (max_rad+1)/2*2);
    }
    return res;
  }
};

问题的解法,实际上就是manacher算法,据说是O(n)的复杂度,该算法的特点就是在新的回文判定中使用了老的信息。

问题解法:

1 对偶问题,实际上有两种对偶形式,一种是以字符为中心,一种是以两相邻字符中间位置为中心。通过在字符中间插入#,使问题转化为第一种的对偶形式,注意的是,字符的最后必须插入#,这样才能保证划归是正确的,因为如果是#b#b,这种模式,实际上和原来的对偶问题是不等价的。

2 利用对偶的历史信息

对偶的历史信息说明了,将要判定的对偶问题的前提条件。当rad[i-k] !=rad[i] -k的时候,说明i位置的最长回文,包含了i+k位置的最长回文,具体分析可以参考manacher算法的最长,则i+k位置的最长回文直接不用计算了。当rad[i-k]=rad[i]-k时候,说明i+k位置的回文长度至少积累rad[i]-k的大小,所以可以直接从rad[i]-k的大小开始探测。

本质上来说,在迭代过程就是使用了回文对偶的性质。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-24 03:37:40

查找字符串中的最长回文问题评述的相关文章

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

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

求字符串中的最长回文子串

题目:给定一个字符串S,求其中的最长的回文子串! 思路:采用动态规划的思想 /** * author :wxg */ #include<iostream> #include<string> using namespace std; /*** 动态规划的思想:字符串 S,以及 f(i,j)表示子字符串 S[i,j] 是否为回文,如果是,f(i,j)=true,否则为 false: ----- true ,i == j f (i, j) = ---- S[i] = S[j] ,j ==

求一个字符串中的最长回文串(Java)

package huiwenchuan; import java.util.Scanner; public class Main { //判断一个字符串是否为回文串 public static boolean isHuiWen(String s) { int len=s.length(); for(int i=0;i<len/2;i++) { if(!(s.charAt(i)==s.charAt(len-i-1))) { return false; } } return true; } /**

字符串中的最长回文字符串

“”“ 形如 abba,abaaba正反序相等的字符串称之为回文字符串 题源:领口 ”“” 1.用键值的形式去记录已经存在的字符和其序列 2.遍历原始的字符串 如果字典中没有则存入  如果有 则对其进行回文检测 3.若出现回文字符串,与现在的进行比较 #但是 单单以键值对形式存储 字符和序列  如原始字符串为 ‘abcacbae’ ,和‘abcaddedda’ 这种字符串 那么原先设计的程序就会崩溃 #要找到一个 判别当前字符串的在原字符串中的有效起始位置. kill:通过 键 列表 形式的键值

[hdu3068 最长回文]Manacher算法,O(N)求最长回文子串

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 题意:求一个字符串的最长回文子串 思路: 枚举子串的两个端点,根据回文串的定义来判断其是否是回文串并更新答案,复杂度O(N3). 枚举回文串的对称轴i,以及回文半径r,由i和r可确定一个子串,然后暴力判断即可.复杂度O(N2). 在上一步的基础上,改进判断子串是否是回文串的算法.记fi(r)=(bool)以i为对称轴半径为r的子串是回文串,fi(r)的值域为{0, 1},显然fi(r)是关于r

【HDOJ3068】最长回文(manacher)

题意:求一个由小写字母组成的字符串中的最长回文长度 cas<=120 n<=110000 思路:试manacher板子 1 var a:array[0..300000]of char; 2 p:array[0..300000]of longint; 3 ch:ansistring; 4 len,n,i,mx,id,ans:longint; 5 6 function min(x,y:longint):longint; 7 begin 8 if x<y then exit(x); 9 exi

(Manacher Algorithm, 中心拓展法,动态规划) leetcode 5. 最长回文串

解法一:中心拓展法.从下标为0开始遍历,将每个元素当作回文串中心,向两边拓展. 1)以这个字符为中心的回文串的长度(奇数串): 2)以这个字符和下个字符为中心的回文串的长度(偶数串). 注意:既要统计回文串为奇数时,又要统计回文串为偶数时.当 s[left]!=s[right] 时,left多减了1,right多加了1,所以在计算回文串开头时要把left+1,长度要是(right-1)-(left+1)-1 = right - left -1 class Solution { public: s

最长回文子字符串的长度

回文是指正着读和倒着读,结果相同,比如abcba或abba,题目是要在一个字符串中要到最长的回文子串 首先我们可以考虑一般的情况,先从字符串中取出任意一个子串,判断其是不是回文字符串,这种方法可以称之为暴力求解法,故时间复杂度可以达到o(n3) 代码如下所示: import java.util.*; public class Palindrome { //判断回文的函数 public boolean isHuiWen(String A, int n){ int k = n / 2; for (i

hiho#1032 : 最长回文子串 (manacher算法O(n)时间求字符串的最长回文子串 )

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一