p2758 編輯距離
一道典型的線性 dp題。
像這種線性動態規劃,一種常見的狀態定義方法是:用 \(f_i\) 表示前 \(i\) 個元素滿足要求(只考慮前 \(i\) 個元素)時的最佳答案。
因此我們很自然地想到用 \(f(i,j)\) 表示將 \(a[1..i]\) 轉換為 \(b[1..j]\) 所需的最少操作次數,\(f(n,m)\) 就是問題的答案(\(n,m\) 分別表示字串 \(a,b\) 的長度)。
線性 dp 中,狀態轉移通常只需要考慮最後一點。
請設想這樣一種場景,\(a[1..i]\) 經過若干次操作被改成了 \(b[1..j]\),且最後一步操作是在\(a\) 的末尾進行的。我們不由地想到,這最後一步操作只可能是以下三種:
刪除 \(a\) 末尾的字元;
在 \(a\) 的末尾插入乙個字元;
修改 \(a\) 末尾的字元。
於是我們發現,有三種策略可以把 \(a[1..i]\) 修改為 \(b[1..j]\):
先把 \(a[1..i-1]\) 變得跟 \(b[1..j]\) 一樣,再刪除 \(a\) 末尾的字元;
先把 \(a[1..i]\) 變得跟 \(b[1..j-1]\) 一樣,再在 \(a\) 的末尾插入乙個字元;
先把 \(a[1..i-1]\) 變得跟 \(b[1..j-1]\) 一樣,再修改 \(a\) 末尾的字元。
狀態轉移式:
\[f(i,j)=\min
\left\
f(i-1,j) & +1 \\
f(i,j-1) & +1 \\
f(i-1,j-1) & +
\left\
0 & ,\textbfa_i=b_j\\
1 & ,\textbfa_i \neq b_j
\end
\right.
\end
\right.
\quad (i>0,j>0)
\]觀察狀態轉移式,注意從左往右的下標變化,下標要麼不變,要麼變小,因此邊界就是下標為 \(0\) 的時候:
\[\begin
f(0,j) & = j \\
f(i,0) & = i \\
f(0,0) & = 0 \\
\end
\]由於從左往右下標要麼不變,要麼變小,因此遞推順序是從小到大列舉 \(i\) 和 \(j\)。
在開始遞推之前,應先求出所有邊界的值。
字串下標從 1 開始。
#include #include #include #include using namespace std;
const int maxn = 2000 + 5;
char a[maxn];
char b[maxn];
int f[maxn][maxn];
int main()
編輯距離(洛谷 P2758 )
洛谷 p2758 編輯距離 題目描述 設a和b是兩個字串。我們要用最少的字元操作次數,將字串a轉換為字串b。這裡所說的字元操作共有三種 1 刪除乙個字元 2 插入乙個字元 3 將乙個字元改為另乙個字元 皆為小寫字母!輸入輸出格式 輸入格式 第一行為字串a 第二行為字串b 字串a和b的長度均小於200...
P2758 編輯距離(洛谷)
傳送門 這道題,dp問題 用dp i j 表示a中的前i個字元與b中的前j個字元轉化的最少次數。那麼當a i b j 時 dp i j dp i 1 j 1 其餘情況,要麼替換要麼刪除要麼新增。替換 dp i j dp i 1 j 1 1 刪除 dp i j dp i 1 j 1 新增 dp i j...
P2758 編輯距離
p2758 編輯距離 設a和b是兩個字串。我們要用最少的字元操作次數,將字串a轉換為字串b。這裡所說的字元操作共有三種 1 刪除乙個字元 2 插入乙個字元 3 將乙個字元改為另乙個字元 皆為小寫字母!輸入格式 第一行為字串a 第二行為字串b 字串a和b的長度均小於2000。輸出格式 只有乙個正整數,...