题目:输入一个字符串,输出该字符串中对称的子字符串的最大长度。比如输入字符串“google”,由于该字符串里最长的对称子字符串是“goog”,因此输出4。
大家一看题目,经常做面试题的同学,就知道这题是微软的面试题。
分析1:我看到这道题目的第一印象就是模拟,从字符串的首字母开始,一个个比较。我们需要用O(n^3)的时间复杂度完成。具体描述可如下代码:
#include <iostream>
#include <cstring>
using namespace std;
bool IsPalindrome(char *pBegin, char *pEnd)
{
if(NULL == pBegin || NULL == pEnd || pBegin > pEnd)
return false;
if(pBegin < pEnd)
{
if(*pBegin != *pEnd)
return false;
IsPalindrome(++pBegin, --pEnd);
}
return true;
}
int GetLongestPalindromeLen(char *pString)
{
if(NULL == pString) return 0;
char *pFirst = pString;
int palindromLen = 1;
int length = strlen(pString) - 1;
char *pLast = &pString[length];
while(pFirst < pLast)
{
char *pMid = pFirst + 1;
while(pMid <= pLast)
{
if(IsPalindrome(pFirst, pMid))
{
int newlength = pMid - pFirst + 1;
if(newlength > palindromLen)
palindromLen = newlength;
}
pMid++;
}
pFirst++;
}
return palindromLen;
}
int main()
{
char str[1000];
while(cin >> str)
{
cout << GetLongestPalindromeLen(str) << endl;
}
return 0;
}
以上就是用O(n^3)的时间来完成求对称字符串最大长度的代码,具体为什么是O(n^3),对编写程序熟练的你肯定能看出来,我在这就不多说了。
分析2:上面我们也特别强调了,时间复杂度的问题,对于O(n^3)的时间来完成一个项目,效率太低,那我们能不能优化一下呢,把时间复杂度降低,提高程序执行的时间效率呢。此时我想到了,求最长公共子字符串的做法,看看用动态规划能不能完成呢?
最长公共子串的算法思想:利用两层循环进行字符比较,if(s1[i] == s1[j]) dp[i][j] = dp[i-1][j-1]+1;else dp[i][j] = max{dp[i][j-1], dp[i-1][j]}; 我们可以根据其算法思想把求最大对称字符串长度转化为求最长公共子串长度。具体描述可如下代码:
int dp[1000][1000];
int GetLongestPalindromeLen(char *pString)
{
memset(dp, 0, sizeof(dp));
int length = strlen(pString);
char *ps = new char[length + 1];
strcpy(ps, pString);
ps = strrev(ps);
//cout << ps << endl;
for(int i = 1; i <= length; ++i)
{
for(int j = 1; j <= length; ++j)
{
if(pString[i - 1] == ps[j - 1]) dp[i][j] = dp[i-1][j-1]+1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[length][length];
}
以上时间复杂度的确得到了优化,时间复杂度为O(n^2)。