案例1、最長回文序列
乙個字串有許多子串行,比如字串abcfgbda,它的子串行有a、bfg、bfgbd,在這些子串行中肯定有回文字串。現在要對任意
字串求其最長的回文子串行。注意,本文不是解決最長回文子串,回文子串是連續的,回文子串行是不連續的。字串abcfgbda
的最長回文子串行為abcba,長度為5。
輸入:包含若干行,每行有乙個字串,字串由大小寫字母構成,長度不超過100。
輸出:對每個輸入,輸出一行,該行有乙個整數,表示最長回文子串行的長度。
example
input:
aabcfgbda
output:15
解題思路:
對任意字串,如果頭和尾相同,那麼它的最長回文子串行一定是去頭去尾之後的部分的最長回文子串行加上頭和尾。如果頭和尾
不同,那麼它的最長回文子串行是去頭的部分的最長回文子串行和去尾的部分的最長回文子串行的較長的那乙個。
設字串為str,dp(i,j)表示str[i..j]的最長回文子串行。
狀態轉移方程如下:
當i > j時,dp[i,j]= 0。
當i = j時,dp[i,j] = 1。
當i < j並且str[i] == str[j]時,dp[i][j] = dp[i+1][j-1]+2;
當i < j並且str[i] ≠ str[j]時,dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
注意如果i+1 == j並且str[i] == str[j]時,dp[i][j] = dp[i+1][j-1]+2 = dp[j,j-1]+2 = 2,這就是「當i > j時f(i,j)=0」的好處。
由於dp[i][j]依賴i+1,所以迴圈計算的時候,第一維必須倒過來計算,從len-1到0。
最後,s的最長回文子串行長度為dp[0][len-1]。
**:
#include #include#include
#include
using
namespace
std;
const
int n = 105
;char
str[n];
intdp[n][n];
intmain()
else
}printf(
"%d\n
",dp[0][len-1
]); }
return0;
}
我們發現計算第i行時只用到了第i+1行,這樣我們便不需要n行,只需要2行即可。
起初先在第0行計算dp[len-1],然後用第0行的結果在第1行計算dp[len-2],再用第1行的結果在第0行計算dp[len-3],以此類推。正在
計算的那行設為now,那麼計算第now行時,就要用第1-now行的結果。這種方法很巧妙。
當計算完成時,如果len是奇數,則結果在第0行;如果是偶數,則結果在第1行。
此空間複雜度為o(n)。
優化後的**:
#include #include#include
#include
using
namespace
std;
const
int n = 105
;char
str[n];
int dp[2
][n];
intmain()
else
cur = 1-cur;
}if(len%2
) else
}return0;
}
學習筆記 動態規劃
動態規劃 多階段決策 意義 求解決策過程最優化的數學方法 基本思想 將待求解的問題分為若干個階段,即若干個互相聯絡的子問題,在求解子問題的過程中逐步推導出原問題的解。核心 在求解子問題的過程中,儲存子問題的解。注1 動態規劃的思想實際上和遞迴相似。都是通過逐步推導,得到答案。而用它們解題時的核心也都...
學習筆記 動態規劃
bullet 先來看乙個問題 小張現在有8個任務可選,每個任務都必須在規定的時間段完成不能多也不能少,而且每個任務都有對應的報酬如下圖,問小張應如何選擇才能拿到最多的報酬?那我們換種方法來解決這個問題吧,首先,每個任務都有選和不選兩種選擇,我們從最後乙個任務開始模擬這個過程。首先我們需要先用乙個陣列...
動態規劃學習筆記
最近開始學習動態規劃演算法,我的理解是動態規劃演算法是乙個用空間換時間的演算法,常用在一些求最解 計數 判斷有無等問題中,且這些問題都存在大量重複的計算。動態規劃的思想就是將已經計算過的資料儲存起來,在下次用到時可以直接取用,這樣就消除了重複計算。而且這也是體現 動態 的地方,就是能根據之前情況進行...