hiho #1032: 最长回文子串
#1032 : 最长回文子串
时间限制:1000ms
单点时限:1000ms
内存限制:64MB
描述
小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。
这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?”
小Ho奇怪的问道:“什么叫做最长回文子串呢?”
小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身为回文串的子串啦~”
小Ho道:“原来如此!那么我该怎么得到这些字符串呢?我又应该怎么告诉你我所计算出的最长回文子串呢?
小Hi笑着说道:“这个很容易啦,你只需要写一个程序,先从标准输入读取一个整数N(N<=30),代表我给你的字符串的个数,然后接下来的就是我要给你的那N个字符串(字符串长度<=10^6)啦。而你要告诉我你的答案的话,只要将你计算出的最长回文子串的长度按照我给你的顺序依次输出到标准输出就可以了!你看这就是一个例子。”
- 样例输入
-
3 abababa aaaabaa acacdas
- 样例输出
-
7 5 3
思路:
1.O(n平方)的方法
记录每个位置,从当前位置,向头尾遍历,直到左右不想等,结束,记录回文串的长度。注意:需要分奇回文和偶回文。
反正hiho上是超时了,看来必须要写一种O(n)复杂度的方法呀。
程序:
1 #include "iostream" 2 #include "string.h" 3 #include "string" 4 5 using namespace std; 6 7 string str; 8 int n, maxnum; 9 10 int main() 11 { 12 cin >> n; 13 while (n--) 14 { 15 cin >> str; 16 maxnum = 1; 17 for (int i = 0; i < strlen(str.c_str()); i++) 18 { 19 int j = 1;//ji 20 while (i - j >= 0 && i + j<strlen(str.c_str())) 21 { 22 if (str[i - j] == str[i + j]) 23 j++; 24 else 25 break; 26 } 27 j = j * 2 - 1; 28 29 int k = 0;//ou 30 while (i - k >= 0 && i + k + 1<strlen(str.c_str())) 31 { 32 if (str[i - k] == str[i + k + 1]) 33 k++; 34 else 35 break; 36 } 37 k = k * 2; 38 39 int tag = j > k ? j : k; 40 if (tag > maxnum) 41 maxnum = tag; 42 } 43 cout << maxnum << endl; 44 } 45 }
2.
Manacher算法。时间O(n),空间O(n)。------完全OK!
主要目的就是要减少计算量,在”中心扩展“法的基础上,节省更多的计算量。下面介绍这种处理方法。
在字符串中间插入符号,将串构造成基回文串
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 7 int longestPalindrome(string s) { 8 string ss = "#"; 9 for (int i = 0; i<s.length(); i++) 10 { 11 ss += s[i]; 12 ss += '#'; 13 } 14 vector<int> P(ss.length(), 0); 15 16 int center = 0, boundary = 0, maxLen = 0, resCenter = 0; 17 for (int i = 1; i<ss.length() - 1; i++) { 18 int iMirror = 2 * center - i; 19 P[i] = (boundary>i) ? min(boundary - i, P[iMirror]) : 0; 20 while (i - 1 - P[i] >= 0 && i + 1 + P[i] <= ss.length() - 1 && ss[i + 1 + P[i]] == ss[i - 1 - P[i]]) 21 P[i]++; 22 if (i + P[i]>boundary) { // 更新边界 23 center = i; 24 boundary = i + P[i]; 25 } 26 if (P[i]>maxLen) { // 更新res 27 maxLen = P[i]; 28 resCenter = i; 29 } 30 } 31 return maxLen; 32 } 33 34 int main() 35 { 36 int n; 37 cin >> n; 38 39 while (n--) 40 { 41 string str; 42 cin >> str; 43 cout << longestPalindrome(str) << endl; 44 } 45 return 0; 46 }