1. 程式人生 > >三維一邊推:最長公共子序列加強版(三串LCS) CAIOJ - 1073 dp lcs

三維一邊推:最長公共子序列加強版(三串LCS) CAIOJ - 1073 dp lcs

題解

與二位lcs類似 列舉三個串的每個位置 狀態轉移考慮5種情況
abc當前位置全相等則由3個串長度全-1的位置轉移過來 lcs+1
ab相等但不與c相等 則由ab長度都-1或c長度-1取max轉移過來
ac相等但不與b相等和bc相等但不與a相等類似
abc互不相等則由a、b或c長度-1取max轉移過來

AC程式碼

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const
int MAXN = 110; int d[MAXN][MAXN][MAXN]; char a[MAXN], b[MAXN], c[MAXN]; int N, M, P; void DPrint(int i, int j, int k) { if (!i || !j || !k) return; if (d[i][j][k] == d[i - 1][j][k]) DPrint(i - 1, j, k); else if (d[i][j][k] == d[i][j - 1][k]) DPrint(i, j - 1, k); else if (d[i][j][k] == d[
i][j][k - 1]) DPrint(i, j, k - 1); else //找到三個都相等的點 DPrint(i - 1, j - 1, k - 1), cout << a[i]; } int main() { #ifdef LOCAL freopen("C:/input.txt", "r", stdin); #endif scanf("%s%s%s", a + 1, b + 1, c + 1); N = strlen(a + 1), M = strlen(b + 1), P = strlen(c + 1); for (int i = 1; i <= N;
i++) for (int j = 1; j <= M; j++) for (int k = 1; k <= P; k++) if (a[i] == b[j] && a[i] == c[k] && b[j] == c[k]) //三個都相等 d[i][j][k] = d[i - 1][j - 1][k - 1] + 1; //abc全減一的lcs+1 else if (a[i] == b[j]) //ab相關 d[i][j][k] = max(d[i][j][k - 1], d[i - 1][j - 1][k]); //(ab)或c減1 else if (a[i] == c[k]) d[i][j][k] = max(d[i][j - 1][k], d[i - 1][j][k - 1]); else if (b[j] == c[k]) d[i][j][k] = max(d[i - 1][j][k], d[i][j - 1][k - 1]); else //都不相等 d[i][j][k] = max(max(d[i - 1][j][k], d[i][j - 1][k]), d[i][j][k - 1] ); //abc任一個減一 cout << d[N][M][P] << endl; DPrint(N, M, P); cout << endl; return 0; }