1040 Longest Symmetric String (25 分)
Given a string, you are supposed to output the length of the longest symmetric sub-string. For example, given Is PAT&TAP symmetric?
, the longest symmetric sub-string is s PAT&TAP s
, hence you must output 11
.
Input Specification:
Each input file contains one test case which gives a non-empty string of length no more than 1000.
Output Specification:
For each test case, simply print the maximum length in a line.
Sample Input:
Is PAT&TAP symmetric?
Sample Output:
11
说实话,这题对时间复杂度和空间复杂度的要求都挺高,算起来改了三版,通不过的思路就不说了,只说可以通过的思路。
1.剪枝(时间复杂度角度)
特别是在对子串求是否为回文串时,选择的对象非常重要,首先,选取子串的顺序从大到小,这样在较长的子串通过后可以直接结束循环而不用去管较短的子串是否为回文串,还有一点就是当获取所有顺序子串的循环进行到子串长度比目前的maxLength值都短,说明接下去的那个循环里的所有子串都会比maxLength值短,因为我们选取子串的顺序是从大到小,所以剩下的子串也就没有必要再判断是否为回文串了,可以直接结束当前循环。这样,时间复杂度就可以符合题目要求。
2.减少内存的使用(空间复杂度角度)
能不存储运行中间结果的地方尽量不存储,我最初是想把所有子串都存储起来放在一个vector数组里,后面再挨个判断是否为回文串且长度为多少,但是这样占用的内存太大,所以我就不再存储每个子串,而是在计算出一个子串的时候直接判断这个子串是否为回文串且得到它的长度。至此,空间复杂度也符合要求。
代码如下:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int maxLength = 0;
int getLength(string str) //若对称则获取长度,否则若不对称则输出0
{int size = str.size();int length = 0;for (int i = 0; i < size; i++){if (str[i] == str[size - i - 1]){length++;}else if(str[i] != str[size - i - 1]){length = 0;break;}}return length;
}void printAllSub(string str) //获取字符串的顺序子串
{int size = str.size();for (int i = 0; i < size; i++){int flag = 0;for (int j = size - i; j>=1; j--){if (j <= maxLength) //剪枝{break;}string tempStr=str.substr(i, j);int temp = getLength(tempStr);if (temp > maxLength){maxLength = temp;flag++;}if (flag == 1) //剪枝{break;}}}
}int main()
{string str;getline(cin,str);printAllSub(str);cout << maxLength;system("pause");return 0;
}
最后有个问题,在得到所有子串的过程中,是递归方式速度更快还是非递归方式速度更快?不过如果我改成递归求所有顺序子串的话,又需要重新剪枝了,那结果好像不好对比。。