Palindrome refers to a given string, which is the same as reading and reading back. such as Ada, the reverse is the ADA is a palindrome string. The longest palindrome substring refers to finding the longest palindrome in a given string.
The following 4 solutions are usually available. The main consideration is the complexity of time.
1: The poor lifting method
Exhaustive all the substring, find is a palindrome string substring, statistics the longest one.
Ask each substring time complexity O (n^2), determine whether the substring is a palindrome O (N), the two are multiplied, so the time complexity is O (n^3).
The code is as follows:
#include <iostream> #include <string>using namespace std;/* The exhaustive method obtains each character string, and then starts from two paragraphs to determine if the character string is a palindrome string. The result of the reading and the inverse of the palindrome is the same. Time complexity is O (n^3) */bool checkpalindrome (const string &s, int i, int j) {for (int k = 0; k < (j-i+1)/2; k++) { //traversal (j-i +1)/2 number if (s[i+k]! = S[j-k]) return false; }return true;} void Longestpadenum (const string &s) {int Begin=0;int maxSize = 0;for (int i = 0; i < s.size (); i++) {for (int j = i+1; J < S.size (); J + +) {if (Checkpalindrome (S, I, j) && j-i > maxSize) {begin = I;maxsize = J-i; The length of palindrome string is j-i+1}}}cout << s.substr (begin, Maxsize+1) << Endl;} int main () {string S;while (cin >> s) {longestpadenum (s);} return 0;}
2: Center Expansion method
Palindrome strings are all starting from the center, we take each letter of the string as the center, extending to both sides, so as to find the longest palindrome string. The complexity of Time becomes O (n^2).
But for each letter to expand as a center, consider whether the palindrome string at this time is even or odd, and then find the longest one.
such as: (1) Like ABA, this is an odd length. Corresponds to code Callout 1: Odd case
(2) A palindrome string of an even size such as ABBA. Processing corresponds to 2 of the callout: even case
The code is as follows:
/* Center expansion method with I as the center of the expansion of the two sides, at this time to consider the palindrome is odd or even, such as Bab and Baab calculation, there are a couple of ways: 1: Odd and even consider 2: in each of the two characters plus a #, the tail can also be added, so that the palindrome must become odd, such as #b#a#b# , #b #a#a#b# length changed to 9 time complexity O (n^2) */int getPalindrome1 (const string &s, int i) {int J = 0;int maxSize = 0;while (i-j >= 0 && I+j < S.size ()) {//1: Odd case if (s[i-j] = = S[i+j]) J++;else break; if (2*j-1 > maxSize) {maxSize = 2*j-1;} j = 0;while (i-j >= 0 && i+j+1 < s.size ()) {//2: Palindrome for even condition only one can be met without dropping any case if (s[i-j] = = s[i+j+1]) j++;else break;} if (2*j > maxSize) {maxSize = 2*j;} return maxSize;} void LongestPadExtend1 (const string &s) {int maxSize = 0;int mid = 0;for (int i = 0; i < s.size (); i++) {int Padlen = GetPalindrome1 (S, i), if (Padlen > maxSize) {maxSize = Padlen;mid = i;}} Output palindrome string int begin = 0;if (maxSize% 2) begin = Mid-maxsize/2;else begin = Mid-maxsize/2 + 1;int end = mid + Maxsize/2;cou T << s.substr (begin, End+1) << Endl;}
Of course there is this other problem of solving a palindrome string that is odd or even. You can add a new character # between the tail of the string and every two characters (assuming that the character # does not appear in the string).at this point, each character is extended to both sides and we will find#the length of the backward polygon extension is odd, and the characters in the string are extended in an even length.(including their own). If it is#extends backwards.3one, as forb#a#a#c,at this time the palindrome string is2if the characters in the string are expanded backwards4one, as ford#b#a#b#c,, the palindrome string is3Therefore, the maximum number of palindrome strings at this time is the number of characters to be expanded backwards.-1. This is actuallyManacherthe first property in the algorithm.
The code is as follows:
/* After the string is added to the #, the J-1 value at each character is the maximum palindrome number for that point */int getPalindrome2 (const string &s, int i) {int j = 0; int maxSize = 0;while (I-j > = 0 && I+j < s.size ()) {if (s[i-j]==s[i+j]) J++;else break;} if (J > maxSize) maxSize = J;return maxSize;} By adding # All palindrome strings are changed to odd void LongestPadExtend2 (const string &s) {string str = "#"; for (int i = 0; i < s.size (); i++) {str + = S[i];str + = "#";} int maxSize = 0;int mid = 0;for (int i = 0; i < str.size (); i++) {int plen = getPalindrome2 (str, i); if (Plen > MaxSize) {maxSize = Plen;mid = i;}} Output palindrome string int begin = 1, end = 1;if (maxSize% 2) { //for odd is #begin = mid-maxsize + 1;end = mid + maxSize-2;} else {begin = Mid-maxsize +2;end = mid + maxSize-2;} for (int j = begin; J <= end; j+=2) cout << str[j];cout << endl;//cout << str << Endl;}
3: Dynamic Planning
We use c[i][j]=1 to denote strings from I to J as palindrome strings, using c[i][j]=0 to denote strings from I to J as non-palindrome strings. Therefore, when C[i][j] is a palindrome string, C[i+1][j-1] will also be palindrome string. At this point the j-i+1 is the longest palindrome string.
Steps based on dynamic planning:
Initialization: c[i][i]=1; If s[i]==s[i+1], then c[i][i+1]=1.
Time complexity: O (n^2), but at this point an additional O (n^2) space is required than the center expansion method
The code is as follows:
/* Dynamic solver back to text string c[i,j] is 1 for the back of the text string from the small label I to J, 0 for the palindrome string is not initialized c[i,i] = 1; if (c[i][i+1] = = C[i][i]) c[i][i+1] = 1 * * #include <iostream> #include <string>using namespace std; #define Maxs IZE 100void Finddplongestpad (string s) {int c[maxsize][maxsize];memset (c, 0, sizeof (c)); int MAXSIZE = 1;int begin = 0;for (i NT i = 0; I < s.size (); i++)//Initialize {C[i][i] = 1;if (I+1 < S.size () && s[i] = = S[i+1]) {C[i][i+1] = 1;maxsize = 2;begin = i;}} for (int len = 3, Len <= s.size (); len++) {for (int i = 0; I <= s.size ()-Len; i++) {int J = i+len-1;if (s[i] = = S[j] & amp;& C[i+1][j-1]) {C[i][j] = 1;maxsize = Len;begin = i;}}} /*for (int i = 0; i < s.size ()-1; i++) {//Dynamic plan iteration for (int j = i+1; J < S.size (); j + +) {if (s[i] = = S[j]) {if (J-i > 1)//exclude c[i,i+1] situation c[i][j] = c[i+1][j-1]+2;} else c[i][j] = 0;if (MaxSize < c[i][j]) {maxSize = C[i][j];begin = i;}}} */for (int i = 0; i < s.size (); i++) {for (int j = 0; J < S.size (), j + +) cout << c[i][j] << ""; cout << ; Endl;} CoUT << s.substr (begin, Begin+maxsize) << Endl;} int main () {string S;while (cin >> s) {Finddplongestpad (s);} return 0;}
4:manacher algorithm-O (n)
(1) Basic points of the algorithm: first, in a very clever way, all possible odd/even length palindrome strings are converted to odd lengths: a special symbol is inserted on both sides of each character. For example, Abba becomes #a #b#b#a#, ABA becomes #a #b#a#. To further reduce the complexity of the encoding, you can add another special character at the beginning of the string, so that you do not have to deal with cross-border issues specifically, such as $ #a #b#a#.
(2) Example:
The following is an example of string 12212321, which, after the previous step, became s[] = "$ #1 #2#2#1#2#3#2#1#";
Then use an array of p[i] to record the length (including S[i]) of the longest palindrome string centered on the character S[i], such as the corresponding relationship of S and P:
S # 1 # 2 # 2 # 1 # 2 # 3 # 2 # 1 #
P 1 2 1 2 5 2 1 4 1 2 1 6 1 2 1 2 1
(P.S. can be seen, p[i]-1 is exactly the total length of the palindrome in the original string)--Properties 1
(3) Calculation P[i]
The following is to calculate P[i], the algorithm adds two helper variable ID and MX, where the ID represents the largest palindrome substring center position, MX is id+p[id], that is, the boundary of the largest palindrome substring.
The key point of this algorithm is here: if mx > I, then P[i] >=min (p[2 * id-i], mx-i).
Code:
if (mx > i) { p[i] = (P[2*id-i] < (mx-i) P[2*id-i]: (Mx-i));} else{ P[i] = 1;}
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.
When P[j] > mx-i, the palindrome string centered on s[j] is not completely contained in a palindrome string centered on S[id], but based on symmetry, it is known that the part surrounded by the two green boxes is the same, that is, the palindrome string centered on the s[i], and its right will expand to the position of MX at least. , which means p[i] >= mx-i. As to whether the post-MX part is symmetrical, it is only one match.
For the case of MX <= i, p[i] could not be made more assumptions, only p[i] = 1, and then to match.
The code is as follows:
#include <iostream> #include <string> #include <algorithm>using namespace std;void Manacherpalindrome (const string &s) {string str = "$#"; for (int i = 0; i < s.size (); i++) {str + = S[i];str + = "#";} int *p = new Int[str.size ()];memset (p, 0, sizeof (int) *str.size ()), int mx = 0, id = 0; ID is the largest position of the current P[id], MX extends to its right boundary that is MX = id+[id]for (int i = 1; i < str.size (); i++) {//Find p[i], the time complexity is O (n) if (mx > i) P[i] = min (p[2*id-i], mx-i), else p[i] = 1;while (I+p[i] < Str.size () && str[i-p[i]] = = Str[i+p[i]])//If not at the beginning plus $ you need to determine if i-p[i] is greater than or equal to 0p[i]++;if (I+p[i] > mx) {mx = i + p[i];id = i;}} Output palindrome string//p[i] for odd number corresponding # even character p[i] maximum is the maximum palindrome +1int maxSize = 0;int mid = 0;for (int i = 0; i < str.size (); i++) {if (maxsi Ze < p[i]) {maxSize = P[i];mid = i;}} for (int k = mid-maxsize + 2; k < mid + maxSize; k=k+2) {cout << str[k];} cout << endl;delete []p;} int main () {string S;while (cin >> s) {manacherpalindrome (s);} return 0;}
this Manacher algorithm uses ID , MX in each cycle, you can directly P[i] To calculate the value of the I in the process of the central palindrome string, you do not have to 1 The comparison is reduced, and finally the length of the longest palindrome string is reached linearly . O (N) of time complexity.
Hiho1032 Longest palindrome substring
Address: http://hihocoder.com/problemset/problem/1032
Code:
#include <memory.h> #include <iostream> #include <algorithm> #include <string>using namespace Std;int findlongestpalindrome (const string &s) {string str = "$#"; for (int i = 0; i < s.size (); i++) {str + = S[i];str += "#";} int *p = new Int[str.size ()];memset (p, 0, sizeof (int) *str.size ()), int id = 0, mx = 0;for (int i = 1; i < str.size (); i++ {if (mx > i) p[i] = min (p[2*id-i], mx-i), else p[i] = 1;while (I+p[i] < Str.size () && Str[i-p[i]]==str[i+p[i]] ) p[i]++;if (I+p[i] > mx) {mx = i+ p[i];id = i;}} int maxSize = 0;for (int i = 0; i < str.size (); i++) {if (MaxSize < p[i]) maxSize = P[i];} delete []p;return maxSize-1;} int main () {int n;cin >> n;while (n--) {string s;cin >> s;cout << findlongestpalindrome (s) << Endl;} return 0;} /*input:3abababaaaaabaaacacdasoutput:753*/
Reference documents:
1:http://www.cnblogs.com/en-heng/p/3973679.html Longest palindrome substring
2:http://www.cnblogs.com/biyeymyhjob/archive/2012/10/04/2711527.htmlo (n) palindrome string (manacher) algorithm
3:https://github.com/julycoding/the-art-of-programming-by-july/blob/master/ebook/zh/01.05.md
4:http://blog.csdn.net/kangroger/article/details/37742639
5:http://blog.163.com/zhaohai_1988/blog/static/2095100852012716105847112/
Longest palindrome substring