今天有点累,不如来个刷个题吧,记得参加腾讯在线笔试的时候遇到过一道题,确实比较懵,所以今天就好好的想了想,这个题来自牛客网...
看到这个图的时候相信大家明白了吧,就是这个题,我一直没有思路,今天突然想起来了,所以就准备解决它。其实这个题主要是运用一个算法思路来解决,最长公共子序列。
仔细想一想,将字符串逆序后与原来的字符串求最长公共子序列不就是这个构造回文吗?这应该很好理解吧,下面简单科普一下最长公共子序列:这中序列不是连续的,意思是可以有间隔,去掉那些干扰项以后,两个序列完全相同,而且要求这个子序列最长。
这类问题和之前 leetcode 上机器人跳到最右下角那个题一样,是一种动态规划的题。而且这种问题的当前位置的解受前面位置的解的影响,假设 s1,s2为两个字符串,i表示s1中第i个字符,j表示s2中第j个字符,那么:
再一次说明一下解题思路:输入字符串S,将字符串S逆序,逆序后的字符串为tmp,然后求S与tmp的最长公共子序列,最后用S的长度减去最长公共子序列的长度,就是需要删除的元素的个数。 相信思路大家明白思路了,下面给出代码。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int LongestStrHui(string &s)
{
string tmp = s;
//逆序
reverse(tmp.begin(), tmp.end());
int len = s.size();
//初始化二维数组,数组多开辟了一些空间,是为了优化
vector<vector<int>> V(len + 1, vector<int>(len + 1, 0));
//根据"公式"开始去找各个位置的公共子序列长度
for (int i = 0; i < len; ++i)
{
for (int j = 0; j < len; ++j)
{
if (s[i] == tmp[j])
V[i + 1][j + 1] = 1 + V[i][j];
else
V[i + 1][j + 1] = max(V[i][j + 1], V[i + 1][j]);
}
}
//整个序列的最长公共子序列
return len - V[len][len];
}
int main()
{
string s;
while (cin >> s)
{
cout << LongestStrHui(s)<<endl;
}
return 0;
}