1. 程式人生 > >2016級算法第四次上機-F.AlvinZH的最“長”公共子序列

2016級算法第四次上機-F.AlvinZH的最“長”公共子序列

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的最“長”公共子序列