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

来源:互联网 发布:沈航网络自助平台套餐 编辑:程序博客网 时间:2024/05/17 13:45

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 <string>#include <iostream>#include <algorithm>using namespace std;#define MAX_LENGTH 1001int 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;}

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

原创粉丝点击