騰訊2016實習筆試題(最長迴文子序列)
阿新 • • 發佈:2019-01-01
問題描述
迴文串:首位相同的字串,如:abba aca
迴文序列:在字串裡面刪除一個或多個字元,剩餘的字元組成迴文串。如:abbceda 刪除"ced",剩餘abba組成迴文序列
最長迴文子序列:一個字串裡面所有迴文序列裡面,最長的序列。
//問題求解
//判斷迴文字串很簡單,直接同時首尾遍歷字串,只要找到不相同的則不是迴文字串
//容易想到的暴力解決辦法,先得到字串的所有子序列,然後判斷序列是否是迴文串,並記錄長度
//從而得到最長的迴文序列,但這種方式肯定是不可取的,
//假如原始字串長度為n,則其所有子序列個數為2^n,時間複雜度太高
//其實這個問題跟最長公共子序列問題類似,因此解決辦法也可以借鑑LCS求解。
//令LPS(m, n)表示下標為m-1到n-1的字串的最長迴文子序列長度,
//現在要求解LPS(m, n+1)的最長迴文子序列長度,如果下標m-1與n處相等,則LPS(m, n+1) = LPS(m+1, n)+2
//否則LPS(m, n+1)就等於LPS(m+1, n)與LPS(m, n+1)的較大值。(思路與LCS基本一致)
//因此可以設計遞迴實現
#include <iostream> #include <string> using namespace std; int LPS_RECU(string str, int m, int n) //表示求m到n的最長迴文子序列長度 { if (m == n) return 1; if (m > n) return 0; if (str[m-1] == str[n - 1]) return LPS_RECU(str, m+1, n - 1) + 2; else { int l1 = LPS_RECU(str, m, n - 1); int l2 = LPS_RECU(str, m+1, n); return l1 > l2 ? l1 : l2; } } int _tmain(int argc, _TCHAR* argv[]) { string str; cin >> str; cout << LPS_RECU(str, 1, str.length()) << endl; return 0; }