POJ-1159 将字符串变成至回文串

POJ 1159

最近发现做算法题最重要的是思路, 一开始的思路正确, 就会非常轻松的做出来, 反之, 会绕好长的路还不一定能出来…

这一题的关键是 最长公共子序列

我并没有想到… 然后呢, 在纸上模拟补齐, 嗯…

举个例子, Aba3bd和它的倒序db3abA, 它们的最长公共子序列是b3b, 所以只要最长的公共子序列对齐即可

1
2
A b a 3   b d
d b 3 a b A

只要对齐的字符越多, 要补的字符就越少

然后中间空出来的部分, 照抄上面的或者下面的
两边不同的部分, 直接错开对齐就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <cstring>
using namespace std;

int main() {
int n;
cin >> n;
string data;
cin >> data;

data = " " + data;

static short dp[5050][5050];
memset(dp, 0, sizeof(dp));

for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (data[i] == data[n - j + 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
}
}
}

cout << n - dp[n][n] << endl;





return 0;
}

滚动数组版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <cstring>
using namespace std;

int main() {
int n;
cin >> n;
string data;
cin >> data;

data = " " + data;

int dp[2][5050];
memset(dp, 0, sizeof(dp));

for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (data[i] == data[n - j + 1]) {
dp[i % 2][j] = dp[(i+1) % 2][j - 1] + 1;
} else {
dp[i % 2][j] = max(dp[i % 2][j - 1], dp[(i+1) % 2][j]);
}
}
}

cout << n - dp[n % 2][n] << endl;


return 0;
}

Author: comwrg
Link: https://comwrg.github.io/2019/03/23/POJ-1159/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.