Title: Enter a string that outputs the maximum length of the symmetric substring in the string. For example, the input string "Google", because the longest symmetric substring in the string is "goog", so output 4.

Analysis: Many people may have written to determine whether a string is a symmetric function, and the topic can be viewed as a reinforced version of the function.

It is not a difficult thing to judge whether a string is symmetrical or not. We can get the string first and end two characters, and judge whether it is equal. If not equal, the string is certainly not symmetric. Otherwise, we will then judge whether the two characters inside are equal, and so on. Based on this idea, it is not difficult to write the following code:

/* The start pointer is pbegin, the end pointer is a pend string
symmetric
/bool Issymmetrical (char* pbegin, char* pend)
{
if (pbegin = = NULL | | Pend = = NULL | | Pbegin > Pend) return
false;
while (Pbegin < pend)
{
if (*pbegin!= *pend) return
false;
pbegin++;
Pend--;
}
return true;
}

To determine if a string pstring is symmetric, we just need to call issymmetrical (Pstring, &pstring[strlen (pstring) –1).

Now we're trying to get the maximum length of the symmetric substring. The most intuitive approach is to get all the substring of the input string, and to judge whether it is symmetric individually. If a substring is symmetric, we get the length of it. By comparing this, you get the length of the longest symmetric substring. So we can write the following code:

/*
Gets the maximum length time complexity of all symmetric substrings
: O (n^3)
/
int getlongestsymmetricallength_1 (char* pstring)
{
if ( pstring = = NULL) return
0;
int symmeticallength = 1;
char* Pfirst = pstring;
int length = strlen (pstring);
while (Pfirst < &pstring[length-1])
{
char* pLast = Pfirst + 1;
while (PLast <= &pstring[length-1])
{
if (issymmetrical (Pfirst, pLast))
{
int newlength = Plast-pfirst + 1;
if (Newlength > Symmeticallength)
symmeticallength = newlength;
}
plast++;
}
pfirst++;
}
return symmeticallength;
}

Let's analyze the time efficiency of the above method. Because we need a double while loop, each cycle requires O (n) time. In addition, we call the issymmetrical in the loop, and the Time of O (n) is required for each invocation. So the time efficiency of the entire function is O (n^3).

Usually O (n^3) is not an efficient algorithm. If we carefully analyze the comparison process of the above methods, we can see that there are many duplicate comparisons. Suppose we need to determine that a substring is in the form of AAA (A is a AAA substring and may contain more than one character). We point the Pfirst to the first character a, Plast to the last character a, and as the two characters are the same, we move the pfirst backwards in the issymtical function and move the Plast forward to determine if a is symmetric. After a few steps, since a is also a substring of the input string, we need to judge once again that it is not symmetric. In other words, we repeatedly judge whether a is symmetric.

The root cause of this repetition is that the comparison of Issymmetrical is carried out from the outside. When judging whether AAA is symmetrical, we do not know if a is symmetrical and therefore need to spend O (n) time to judge. The next time we judge if a is symmetrical, we still need O (n).

If we change one way of thinking, we'll judge from inside to outside. That is, we first judge whether substring a is symmetric. If a is not symmetric, the string that extends one character to each end of the substring is certainly not symmetric. If a is symmetric, then we only need to judge whether a character extended at both ends is equal, and if it is equal, the extended string is symmetric. So when you know if a is symmetrical, you only need O (1) Time to know if AAA is symmetrical.

We can write the following code based on the idea of comparing from inside to outside:

/* obtains maximum length time complexity for all symmetric substrings: O (n^2)/int getlongestsymmetricallength (char* pstring) {if (pstring = NULL)
return 0;
int symmeticallength = 1;
char* pchar = pstring;
while (*pchar!= ' ") {//substrings with odd length char* left = pChar-1;
char* right = Pchar + 1;
while (left >= pstring && *right!= ' i ' && *left = = *right) {left--;
right++; int newlength = right-left-1;
When exiting the while loop, *left!= *right if (Newlength > symmeticallength) symmeticallength = newlength;
Substrings with even length left = Pchar;
right = Pchar + 1;
while (left >= pstring && *right!= ' i ' && *left = = *right) {left--;
right++; } newlength = right-left-1;
When exiting the while loop, *left!= *right if (Newlength > symmeticallength) symmeticallength = newlength;
pchar++;
return symmeticallength; }

Because the length of the substring may be odd, it may be an even number. A string with an odd length is extended from the center of only one character to both ends, while the string with an even length is extended from a center of two characters to both ends. So our code has to take this into account.

In the preceding code, we extend from each end of the string, if the current substring is symmetric, and then judge whether the extended string is symmetric. Because there are O (n) characters in total, each character may extend O (n) times, only O (1) is required at each extension to determine whether it is symmetric, so the time efficiency of the entire function is O (n^2).

Palindrome string Definition: "palindrome string" is a positive and reverse read the same string, such as "level" or "noon" and so is a palindrome string.

Palindrome strings, as the name suggests, that is, the string satisfies the palindrome character substring.

Often have some topics around palindrome string for discussion, such as Hdoj_3068_ longest palindrome, to find the longest palindrome string length. The simple algorithm is to extend each character as the center to the sides in turn, obviously this complexity is O (n^2), on the topic of strings commonly used algorithms have KMP, suffix array, ac automata, this topic using extended KMP can be answered, and its time complexity is very fast O (N*logn). However, today, the author introduces a special algorithm for palindrome string, whose time complexity is O (n), which is the manacher algorithm.

As we all know, it is necessary to judge the parity of the palindrome string, that is, to find a slight gap between the ABA and the ABBA algorithm. However, this algorithm does a simple processing, it is very ingenious to consider the odd length palindrome string and even length palindrome string, that is to insert a separator between each adjacent character, the end of the string should also be added, of course, this separator can not be used in the original string, generally use ' # ' or ' $ ' and other characters. For example:

Original string: Abaab

New string: #a #b#a#a#b#

Thus, the original odd-length palindrome string or odd-numbered 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, which is the center of each character, that is p[i], and the longest palindrome string that is centered on the str[i] character. P[i] Minimum of 1, at this time palindrome string for str[i] itself.

We can write out the 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 string that is centered around Str[i] in the original string.

Prove:

1, obviously l=2*p[i]-1 is the new string of Str[i] as the center of the longest palindrome string length.

2, to Str[i] as 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, the p[i]-1 of the simplification. Get the card.

In the past, we can find P array, and here we use the idea of DP (Dynamic planning), which is to ask for P[i, the previous p[] value has been obtained, we use the special properties of palindrome string can be a big optimization. Let me just post the core code:

for (i=1;i<n;i++)
{
if (maxid>i)
{
p[i]=min (p[2*id-i],maxid-i);
}
else
{
p[i]=1;
}
while (Str[i+p[i]]==str[i-p[i]])
{
p[i]++
}
if (P[i]+i>maxid)
{
maxid=p[i]+i;
Id=i
}
}

In order to prevent p[i] from extending to both sides, we need to add a special character to the front and back of the array, so that the p[0]= ' $ ' last position defaults to ' no special treatment '. In addition, we use the MAXID variable to record in the palindrome string before I, extend to the far right position, and take the ID value of this MAXID with ID. By following this sentence, the algorithm avoids a lot of unnecessary duplicate matching.

if (maxid>i)
{
p[i]=min (p[2*id-i],maxid-i);
}

So how does this sentence come from, in fact, is the use of the symmetry of palindrome string, the following figure:

J=2*id-1 that is I on the ID of the symmetrical point, according to the symmetry, P[j] palindrome string can also be symmetrical to I this side, but if P[J] palindrome string symmetry over after Maxid, beyond the part of the symmetry can not come over, the following figure, so here P[i] The lower bound is the lesser of the two, P[i]=min (p[2*id-i],maxid-i).

The effective comparison times of the algorithm is MAXID, so the time complexity of the algorithm is O (n).

Attached hdoj_3068_ the longest palindrome code:

#include <stdio.h> #define M 110010 Char b[m],a[m<<1];
int p[m<<1];
int Min (int a,int b) {return a<b?a:b;}
int main (void) {int i,n,id,maxl,maxid;
while (scanf ("%s", &b[1])!=eof) {maxl=maxid=0;
for (i=1;b[i]!= '; i++) {a[(i<<1)]=b[i];
a[(i<<1) +1]= ' # '; } a[0]= '? ';
a[1]= ' # ';
N= (i<<1) +2;a[n]=0;
maxid=maxl=0;
for (i=1;i<n;i++) {if (maxid>i) {p[i]=min (p[2*id-i],maxid-i);
else {p[i]=1;
} while (A[i+p[i]]==a[i-p[i]]) {p[i]++;
} if (P[i]+i>maxid) {maxid=p[i]+i;
Id=i;
} if (P[I]>MAXL) {maxl=p[i];
} printf ("%d\n", MaxL-1); RetUrn 0;
}