The longest palindrome substring manacher o (n) solution + interval DP O (n2) solution

Source: Internet
Author: User

Turn from blog: www.cnblogs.com/mickole/articles/3578298.html

Title: (Alternative topics can be found in the Pat ladder exercises, of course, the problem N3 can be too)

A string of length n (n Large), which is the longest palindrome in the string. (Baidu 2014 School Recruit written questions) The topic pointed out "N is very big", that is, we do not want to go through the way to find this string, I think of a solution, time complexity should not be high, but I can not figure out the complexity of this algorithm is how much, first of all, say what is a palindrome string: Palindrome string refers to the same string from left to right and right to left, such as "1221" or "12321" are palindrome strings. There are many solutions to this problem. Solution One: Manacher algorithm (O (n))

As we all know, it is necessary to judge the parity of the palindrome, that is, the algorithm of ABA and ABBA has a slight difference. However, this algorithm does a simple processing, very clever to the odd-length palindrome string and even-length palindrome unified consideration, that is, each adjacent character inserted a delimiter, the end of the string to add, of course, this delimiter can not appear in the original string, the general may use ' # ' or ' $ ' and other characters. For example:
Original string: Abaab
New string: #a #b#a#a#b#
In this way, the original odd-length palindrome string is still odd length, even length of the "#" as the center of the odd palindrome string.
Next is the central idea of the algorithm, using an auxiliary array p to record the longest palindrome radius centered on each character, that is, P[i], which records the longest palindrome radius centered on the s[i] character. P[i] Minimum is 1, at this time palindrome string for str[i] itself.

In order to prevent p[i] from expanding on both sides of the array, we need to add a special character to the front and back of the array, so that the p[0]= ' $ ', the last position defaults to ' + ' does not require special handling
We can write out its p array for the above example, as follows:
New string: # a # b # # A # a # b #
P[]: 1 2 1 4 1 2 5 2 1 2 1
We can prove that p[i]-1 is the length of a palindrome in the original string centered on S[i].
Prove:
1, obviously l=2*p[i]-1 is the new string in the S[i] as the center of the longest palindrome string length.
2, S[i] is the center of the palindrome string must be the beginning and end of the #, for example, "#b #b#" or "#b #a#b#" so L minus the first or last ' # ' character is twice times the length of the original string, that is, the original string length is (L-1)/2, simplifying the p[i]-1.

So how to calculate p[i]? The algorithm adds two helper variables (in fact one is enough, two clearer) ID and MX, where the ID represents the location of the largest palindrome substring center, and MX is id+p[id], which is the boundary of the largest palindrome substring. In order to get the P array in the past, the use of the DP (Dynamic planning) of the idea, that is, to seek p[i], the front of the p[] value has been obtained, we use Palindrome string special properties can be a big optimization. I'll first paste the core code:

The key point of this algorithm is here:

if (mx > i)

P[i] >= MIN (p[2 * id-i], mx-i)

This is the string card I have been very long. In fact, if you write it a little more complicated, it will be easier to understand:

j = 2 * id-i, that is, J is the symmetric point about ID.
if (Mx-i > P[j]) 
    P[i] = p[j];
else/* P[j] >= mx-i *
    /p[i] = mx-i;//p[i] >= mx-i, take the minimum, and then match the update.

Of course, the code is still not clear enough, or the use of diagrams to understand the more easily.
When Mx-i > P[j], the palindrome string centered on S[j] is contained in a palindrome string centered on S[id], because I and J are symmetric, the palindrome string centered on s[i] is necessarily contained in a palindrome string centered on S[id], so there must be p[i] = P[j], see the figure below.

When P[j] >= mx-i, the palindrome string centered on s[j] is not necessarily completely contained in a palindrome string centered on S[id], but based on symmetry, the two green boxes in the image below are surrounded by the same part, that is, the palindrome string centered on the s[i], It will expand to the right at least to the MX position, i.e. P[i] >= mx-i. As to whether the post-MX part is symmetrical, it can only be honestly matched.

For the case of MX <= i, p[i] could not be made more assumptions, only p[i] = 1, and then to match.

Core code:

void PK ()
{
    int i;
    int mx = 0;
    int id;
    for (I=1; i<n; i++)
    {
        if (mx > i)
            p[i] = MIN (P[2*id-i], mx-i);        
        else
            p[i] = 1;
        for (; Str[i+p[i]] = = Str[i-p[i]]; p[i]++)
            ;
        if (P[i] + i > mx)
        {
            mx = p[i] + i;
            id = i;}}
}

Solution Two: Dynamic Programming (DP), Interval DP

Thought: DP's consideration stems from the brute force method, the brute force method is to find all substrings of a string, need O (n^2) overhead, and then for each substring need O (n) cost to determine whether it is a palindrome, so the violence scheme is O (n^3), but here is a problem, is in the time of violence have repeated judgment;

For example, if the substring x is a palindrome, then SxS is a palindrome, and if X is not a palindrome, then SxS is not a palindrome, in addition, the SS is a palindrome. So here we use DP we can construct the DP state array in the order of sub-string length from small to large, use a two-dimensional array dp[i][j] to record whether the substring [i-j] is a palindrome substring, then we have the initialization and the bottom-up scheme;

Initialize: single string and equal double string for palindrome

Bottom-up construction: x[i]==x[j] && dp[i+1][j-1]==1 dp[i][j] = 1

complete code for 2 solutions:

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include < vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath&
Gt

#include <cstdlib> #include <ctime> #include <stack> #include <sstream> #include <string>

using namespace Std;


const int MAXN = 1100;
    String BYDP (string s) {bool DP[MAXN][MAXN];
    Memset (Dp,0,sizeof (DP));
    int n = s.length ();
    int maxlen = 1,lbegin = 0;
    The length of 1 is handled separately for (int i = 0;i<n;++i) {Dp[i][i] = 1;
    }///length is 2 separate processing.
            for (int i = 0;i<n-1;++i) {if (s[i]==s[i+1]) {dp[i][i+1] = 1;
            MaxLen = 2;
        Lbegin = i;
            }} for (int len = 3;len <=n;++len) {for (int i = 0;i+len-1<n;++i) {int j = i+len-1;
                if (Dp[i+1][j-1] && s[i]==s[j]) {dp[i][j] = 1; MaxLen =Len
            Lbegin = i;
}}} return S.substr (Lbegin,maxlen);
    The string Bymanacher (string s) {///is converted to a new string int n = s.length ();///The original string length string news;
    news+= ' @ '; news+= ' # ';
        for (int i = 0;i<n;++i) {news+=s[i];
    news+= ' # ';
    }//solve P int P[2*MAXN];
    n = 2*n+2;
    memset (P,0,sizeof (p));
    int Id=0,mx=0;///***id is the center position of the largest palindrome substring, not the center position of the longest palindrome string int maxcent = 0, maxr = 0;;
        for (int i = 1;i<n;++i) {Int J = 2*id-i;///j is i about the ID of the symmetric point if (mx>i) p[i] = min (p[j],mx-i);
        else p[i] = 1;

        while (i+p[i]<n && i-p[i]>0 && news[i+p[i]] = = News[i-p[i]]) p[i]++;
            if (P[I]+I&GT;MX) {//update location ID = i;
        mx = p[i]+i;
            } if (P[I]&GT;MAXR) {maxcent = i;
        MAXR = P[i];
    }} string ans;
    int maxbegin = Maxcent-maxr+1,maxend = maxcent+maxr-1; for (int i = maxbegin;i<=maxend;++i) {if (NEWs[i]! = ' # ') ans + = news[i];
} return ans;
    } int Main () {string S;
    Getline (cin,s);
    s = BYDP (s);
    s = bymanacher (s);

    Cout<<s.length ();

return 0;

 }



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.