最长回文字符串
题目描述
Catcher 是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的有效密码串吗?
(注意:记得加上while处理多个测试用例)
输入描述:
输入一个字符串
输出描述:
返回有效密码串的最大长度
思路分析:
- 思路1:题目的含义最初理解错了以为回文字符串只会出现在开始和结尾,结果测试用例没过,实际上,这个题目还是要找字符串的最大回文字符串,而不管在什么位置;暴力依次搜索即可;一个小技巧是,搜索可以从字符串最后往前搜索,这样只要找到返回即可认为是最大的,而不是从小依次搜索;
- 思路2:通过思路1是能够获得答案的,但很明显,运算复杂度较高(o(n^2)),无法满足需要,而使用动态规划,复杂度仍然是需要构建DP[N][N],复杂度仍然如此,这是少有的使用DP没有优化效果的题目;有一种算法时间复杂度只需要 O(N),不过该解法比较复杂,个人认为没必要掌握。该算法的名字叫 Manacher’s Algorithm(马拉车算法)
- 思路1:代码:
#include<iostream>
#include<string>
using namespace std;
bool judgehuiwen(const string& input){
int str_len = strlen(input.c_str());
if (input.empty()) return false;
for (int i = 0; i <= str_len/2; i++)
{
if (input[i] != input[str_len -1- i]) {
return false;
}
}
return true;
}
int MatchingTarget(const string& input) {
bool flag = false;
int num = 0;
if (input.empty()) {
return 0;
}
int str_len = strlen(input.c_str());
for (int i = 0; i < str_len; i++)
{
for (int j = i; j < str_len; j++)
{
if (input[j] == input[i]) {
string tmp(input.begin()+i, input.begin() + j+1);
if (judgehuiwen(tmp)) {
int tmpstr_len = strlen(tmp.c_str());
num = std::max(num, tmpstr_len);
}
}
}
}
return num;
}
int test_maxValidPassword() {
string input;
while (cin >> input)
{
int num;
num = MatchingTarget(input);
printf("%d\n", num);
}
return 0;
}
参考链接: