三维一边推:最长公共子序列加强版(三串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;
}

猜你喜欢

转载自blog.csdn.net/CaprYang/article/details/85097118
LCS