2016級算法第四次上機-F.AlvinZH的最“長”公共子序列
阿新 • • 發佈:2017-12-04
printf 得到 line include har () markdown source mar
940 AlvinZH的最“長”公共子序列
思路
DP,難題。
\(dp[i][j]\) :記錄A的前i個字符與B的前j個字符變成相同需要的最小操作數。
初始化:dp[i][0] = i, dp[0][i] = i。分別代表i次刪除or添加操作。
三種操作得到dp[i][j],取其中最小值:
- 替換:可能不需要替換,所以是dp[i-1][j-1]+Same(A[i-1],B[j-1]);
- 刪除:dp[i-1][j]+1;
- 添加:dp[i][j-1]+1。
千萬不要糾結操作的序列是A還是B!
其實這是《算法導論》上一個“編輯距離”問題,比較經典,有興趣的同學可以看看書or百度看看。
分析
沒法分析,DP豈是我等凡人能理解的,sad。
稍微分析,時間復雜度O(n^2)。
參考代碼一
//
// Created by AlvinZH on 2017/10/16.
// Copyright (c) AlvinZH. All rights reserved.
//
#include <cstdio>
#include <cstring>
char A[1005], B[1005];
int dp[1005][1005];//記錄A的前i個字符轉換到B的前j個字符的最小操作數
inline int Same(char a, char b) {
if(a == b) return 0;
else return 1;
}
inline int MIN(int a, int b, int c) {
if(a > b) a = b;
if(a > c) a = c;
return a;
}
int main()
{
while(~scanf("%s %s", A, B))
{
int lenA = strlen(A);
int lenB = strlen(B);
for (int i = 0; i <= lenA; ++i)
dp[i][0] = i;//i次刪除操作
for (int i = 0; i <= lenB; ++i)
dp[0][i] = i;//i次添加操作
for (int i = 1; i <= lenA; ++i) {
for (int j = 1; j <= lenB; ++j) {
dp[i][j] = MIN(dp[i-1][j-1]+Same(A[i-1],B[j-1]), dp[i-1][j]+1, dp[i][j-1]+1);
//MIN(替換, 刪除, 添加)
}
}
printf("%d\n", dp[lenA][lenB]);
}
}
2016級算法第四次上機-F.AlvinZH的最“長”公共子序列