2017年腾讯实习生在线笔试编程题(1)

1.题目:构造回文

https://www.nowcoder.com/questionTerminal/28c1dc06bc9b4afd957b01acdf046e69
来源:牛客网
给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串。如何删除才能使得回文串最长呢?
输出需要删除的字符个数。

输入描述:
输入数据有多组,每组包含一个字符串s,且保证:1<=s.length<=1000.
输出描述:
对于每组数据,输出一个整数,代表最少需要删除的字符个数。
输入
abcda
google
输出
2
2

解题思路
(1)把字符串旋转形成另外一个字符串,称为旋转字符串;
(2)求原字符串s1与旋转字符串s2中,最长公共子串的长度;
(3)删除的字符数目 = 原字符串的长度 - 最长公共子串的长度。
需要解决的子问题:
求两个字符串s1和s2中最长公共子串的长度。
子问题的求解方式:动态规划
设 MaxLen(i,j)表示s1左边i个字符与s2左边j个字符的最长公共子串长度,则子问题的解为MaxLen(strlen(s1),strlen(s2));
MaxLen(i,j)的求解方式为:
若s1第i个字符与s2第j个字符相匹配,则 return 1+MaxLen(i-1,j-1);
否则:return max(MaxLen(i-1,j),MaxLen(i,j-1))
边界条件:
MaxLen(i,n)=0; for n in 0 to strlen(s2)
AC代码


#include 
#include 
#include 

using namespace std;

#define MAX_LENGTH 1001
int maxLen[MAX_LENGTH][MAX_LENGTH];

int main()
{
    string s1;
    while (cin >> s1){
        string s2(s1.rbegin(), s1.rend());
        for (int i = 0; i < s1.length(); i++){
            maxLen[i][0] = 0;
            maxLen[0][i] = 0;
        }
        for (int i = 1; i <= s1.length(); i++){
            for (int j = 1; j <= s2.length(); j++){
                if (s1[i-1] == s2[j-1])
                    maxLen[i][j] = 1 + maxLen[i - 1][j - 1];
                else{
                    maxLen[i][j] = max(maxLen[i - 1][j], maxLen[i][j - 1]);
                }
            }
        }
    cout << s1.length() - maxLen[s1.length()][s1.length()] << endl;
    }
    return 0;
}

知识点解析
动态规划求解两个字符串的公共子串

你可能感兴趣的:(在线编程)