九度OJ 1528 最长回文子串 -- Manacher算法

题目地址:http://ac.jobdu.com/problem.php?pid=1528

题目描述:

回文串就是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。
回文子串,顾名思义,即字符串中满足回文性质的子串。
给出一个只由小写英文字符a,b,c...x,y,z组成的字符串,请输出其中最长的回文子串的长度。

输入:

输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串,字符串的长度不大于200000。

输出:

对于每组测试用例,输出一个整数,表示该组测试用例的字符串中所包含的的最长回文子串的长度。

样例输入:
abab
bbbb
abba
样例输出:
3
4
4
来源:
腾讯2013年实习生招聘二面面试题

自己比较野蛮的方法

#include <stdio.h>
#include <string.h>
 
int LenOfMaxPalindrome(char str[], int len, int low, int high){
    int sum = 0;
    while (low >= 0 && high < len){
        if (str[low] == str[high]){
            sum += 2;
            --low;
            ++high;
        }
        else
            break;
    }
    return sum;
}
 
int MaxPalindrome (char str[]){
    int len = strlen (str);
    int mid;
    int len1;
    int len2;
    int max;
 
    if ((len >= 2) && (str[0] == str[1]))
        max = 2;
    else
        max = 1;
    for (mid=1; mid<len-1; ++mid){
        len1 = len2 = 0;
        len1 = LenOfMaxPalindrome(str, len, mid - 1, mid + 1) + 1;
        if (str[mid] == str[mid + 1]){
            len2 = LenOfMaxPalindrome(str, len, mid - 1, mid + 2) + 2;
        }
        if (len1 < len2)
            len1 = len2;
        if (max < len1)
            max = len1;
    }
     
    return max;
}
 
int main(void){
    char str[200001];
 
    while (scanf ("%s", str) != EOF){
        printf ("%d
", MaxPalindrome (str));
    }
 
    return 0;
}

O(n)的回文子串Manacher算法(详细算法讲解见参考资料)

算法代码实现如下:

#include <stdio.h>
 
void Manacher (char str[], int len, int Radix[]){
    int mx = 0;    //记录被影响到的最远的位置
    int id = 0;    //最长影响串的位置
    Radix[0] = 0;
    int i;
    for (i=1; i<len; ++i){
        Radix[i] = 1;
        if (mx > i){
            Radix[i] = Radix[2 * id - i];
            if (mx - i < Radix[i])
                Radix[i] = mx - i;
        }
        while (str[i - Radix[i]] == str[i + Radix[i]])
            ++Radix[i];
        if (i + Radix[i] > mx){
            mx = i + Radix[i];
            id = i;
        }
    }
}
 
int Preproccess (char str[], char old_str[]){
    int index;
    int len;
    char middle = '#';
    str[0] = '$';
    str[1] = middle;
    index = 0;
    len = 2;
    while (old_str[index]){
        str[len++] = old_str[index++];
        str[len++] = middle;
    }
    str[len] = '?';
    return len;
}
 
int main(void){
    char old_str[200001];
    char str[400004];
    int Radix[400004];
    int len;
    int i;
    int ans;
 
    while (scanf ("%s", old_str) != EOF){
         len = Preproccess (str, old_str);
         Manacher (str, len, Radix);
         ans = 0;
         for (i=1; i<len; ++i){
            if (ans < Radix[i])
                ans = Radix[i];
         }
         printf ("%d
", ans - 1);
    }
    return 0;
}

参考资料:http://tiankonguse.com/blog/?p=84

                 http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.html

                 http://www.akalin.cx/longest-palindrome-linear-time

                 http://leetcode.com/2011/11/longest-palindromic-substring-part-i.html

                 http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html


相思题目:https://oj.leetcode.com/problems/longest-palindromic-substring/

原文地址:https://www.cnblogs.com/liushaobo/p/4373781.html