uva 531 Compromise(LCS)
2011 ワード
タイトル接続:531-Compromise
2つの文字列を与えて、それぞれいくつかの文字列を含んで、2つの文字列の最も長い共通のサブシーケンスを求めて、そして最も長い方案を出力して、もし多種がいずれかを出力することができるならば.
解題構想:普通の最長男シーケンス問題は、一般解と同じですが、パスを記録するには、私のやり方は2つの各配列を開いて移動方式を記録し、x[p][q],y[p][q]です.x[p][q]==p-1&&y[p][q]==q-1の場合、2つの文字列が等しいことを示す.
2つの文字列を与えて、それぞれいくつかの文字列を含んで、2つの文字列の最も長い共通のサブシーケンスを求めて、そして最も長い方案を出力して、もし多種がいずれかを出力することができるならば.
解題構想:普通の最長男シーケンス問題は、一般解と同じですが、パスを記録するには、私のやり方は2つの各配列を開いて移動方式を記録し、x[p][q],y[p][q]です.x[p][q]==p-1&&y[p][q]==q-1の場合、2つの文字列が等しいことを示す.
#include <stdio.h>
#include <string.h>
const int N = 105;
const int M = 30;
int max(int a, int b) { return a > b ? a : b; }
int n, m, ans[N], dp[N][N], x[N][N], y[N][N];
char a[N][M], b[N][M];
void Init() {
n = m = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(x, -1, sizeof(x));
memset(y, -1, sizeof(y));
memset(dp, 0, sizeof(dp));
}
int read() {
int flag = 0;
while (1) {
if (scanf("%s", a[n]) != 1) {
flag = 1;
break;
}
if (strcmp(a[n], "#") == 0) break;
n++;
}
while (1) {
if (scanf("%s", b[m]) != 1) {
flag = 1;
break;
}
if (strcmp(b[m], "#") == 0) break;
m++;
}
return flag;
}
void solve() {
memset(ans, -1, sizeof(ans));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (strcmp(a[i - 1], b[j - 1]) == 0) {
dp[i][j] = dp[i - 1][j - 1] + 1;
x[i][j] = i - 1;
y[i][j] = j - 1;
}
else {
if (dp[i - 1][j] > dp[i][j - 1]) {
dp[i][j] = dp[i - 1][j];
x[i][j] = i - 1;
y[i][j] = j;
}
else {
dp[i][j] = dp[i][j - 1];
x[i][j] = i;
y[i][j] = j - 1;
}
}
}
}
int sum = dp[n][m] - 1, p = n, q = m;
while (1) {
if (x[p][q] == -1 || y[p][q] == -1) break;
if (sum < 0) break;
if ((p == x[p][q] + 1) && (q == y[p][q] + 1)) {
ans[sum--] = x[p][q];
}
int t = p;
p = x[t][q], q = y[t][q];
}
}
int main() {
while (1) {
Init();
if (read()) break;
solve();
if (dp[n][m]) {
for (int i = 0; i < dp[n][m] - 1; i++)
printf("%s ", a[ans[i]]);
printf("%s
", a[ans[dp[n][m] - 1]]);
}
}
return 0;
}