DP字符串类型题汇总
- 最长公共子串(LCS)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int d[maxn][maxn];
char a[maxn], b[maxn];
int la, lb;
int main() {
#ifdef LOCAL
freopen("E:\\Cpp\\1.in", "r", stdin);
#endif
scanf("%s%s", a, b);
la = strlen(a);
lb = strlen(b);
memset(d, 0, sizeof(d));
for (int i = 1; i <= la; i++)
for (int j = 1; j <= lb; j++) {
if (a[i - 1] == b[j - 1])
d[i][j] = d[i - 1][j - 1] + 1;
else
d[i][j] = max(d[i - 1][j], d[i][j - 1]);
}
int len = d[la][lb];
printf("%d\n", len);
stack<char> ans;
int i = la, j = lb;
while (d[i][j]) {
if (d[i][j] == d[i - 1][j])
i--;
else if (d[i][j] == d[i][j - 1])
j--;
else {
ans.push(a[i - 1]);
i--;
j--;
}
}
while (!ans.empty()) {
printf("%c", ans.top());
ans.pop();
}
return 0;
}
- 最短公共父串
#include <bits/stdc++.h>
using namespace std;
const int maxn = 15;
int d[maxn][maxn], f[maxn][maxn];
int len1, len2, cnt;
char a[maxn], b[maxn];
int main() {
#ifdef LOCAL
freopen("E:\\Cpp\\1.in", "r", stdin);
#endif
scanf("%s", a + 1);
scanf("%s", b + 1);
len1 = strlen(a + 1), len2 = strlen(b + 1);
int m = max(len1, len2);
for (int i = 0; i <= m; i++) {
d[i][0] = d[0][i] = i;
f[i][0] = f[0][i] = 1;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (a[i] == b[j]) {
d[i][j] = d[i - 1][j - 1] + 1;
f[i][j] = f[i - 1][j - 1];
} else {
d[i][j] = min(d[i - 1][j], d[i][j - 1]) + 1;
if (d[i - 1][j] < d[i][j - 1])
f[i][j] = f[i - 1][j];
else if (d[i][j - 1] < d[i - 1][j])
f[i][j] = f[i][j - 1];
else
f[i][j] = f[i - 1][j] + f[i][j - 1];
}
}
}
printf("%d %d", d[len1][len2], f[len1][len2]);
}
#include <bits/stdc++.h>
using namespace std;
const int maxn = 15;
int d[maxn][maxn];
int flag[maxn][maxn];
char str[maxn], str1[maxn];
char P[maxn];
int k;
void print(int l, int r) {
if (l == 0 && r == 0)
return;
if (flag[l][r] == 0) {
print(l - 1, r - 1);
printf("%c", str[l]);
} else if (flag[l][r] == 1) {
print(l - 1, r);
printf("%c", str[l]);
} else {
print(l, r - 1);
printf("%c", str1[r]);
}
}
void LCS() {
memset(flag, 0, sizeof(flag));
int n = strlen(str + 1);
int m = strlen(str1 + 1);
for (int i = 1; i <= n; i++)
flag[i][0] = 1;
for (int i = 1; i <= m; i++)
flag[0][i] = -1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (str[i] == str1[j]) {
d[i][j] = d[i - 1][j - 1] + 1;
flag[i][j] = 0;
} else {
if (d[i - 1][j] > d[i][j - 1]) {
d[i][j] = d[i - 1][j];
flag[i][j] = 1;
} else {
d[i][j] = d[i][j - 1];
flag[i][j] = -1;
}
}
}
}
print(n, m);
printf("\n");
}
int main() {
while (scanf("%s%s", str + 1, str1 + 1) != EOF) {
LCS();
}
return 0;
}
- 插入字符生成回文串
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
int n, m;
int d[maxn][maxn];
int dp(string s, string t) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i - 1] == t[j - 1])
d[i][j] = d[i - 1][j - 1] + 1;
else
d[i][j] = max(d[i - 1][j], d[i][j - 1]);
}
return d[n][m];
}
int main() {
#ifdef LOCAL
freopen("E:\\Cpp\\1.in", "r", stdin);
#endif
string s;
cin >> s;
string t(s.rbegin(), s.rend());
n = s.size();
m = n;
cout << n - dp(s, t);
return 0;
}
- 分割字符串生成回文子串
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int d[maxn];
int s[maxn][maxn];
string st;
int work() {
int len = st.size();
memset(s, 0, sizeof(s));
for (int i = 0; i < len; i++) {
int p, q;
s[i][i] = 1;
p = i - 1;
q = i + 1;
while (p >= 0 && q < len && st[p] == st[q]) {
s[p][q] = 1;
p--;
q++;
}
p = i - 1;
q = i;
while (p >= 0 && q < len && st[p] == st[q]) {
s[p][q] = 1;
p--;
q++;
}
p = i;
q = i + 1;
while (p >= 0 && q < len && st[p] == st[q]) {
s[p][q] = 1;
p--;
q++;
}
}
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> st;
work();
int len = st.size();
for (int i = 0; i < len; i++)
d[i] = 100000;
for (int i = 0; i < len; i++) {
int j = 0;
if (s[0][i])
d[i] = 1;
else
for (j = 0; j < i; j++) {
if (s[j + 1][i])
d[i] = min(d[i], d[j] + 1);
}
}
cout << d[len - 1] << endl;
}
return 0;
}
- 删除最少字符使两串相同
int delet(string s, string t) {
int n = s.size();
int m = t.size();
if (n == 0)
return m;
if (m == 0)
return n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i - 1] == t[j - 1])
d[i][j] = d[i - 1][j - 1] + 1;
else
d[i][j] = max(d[i - 1][j], d[i][j - 1]);
}
return n + m - 2 * d[n][m];
}
- 修改或删除最少字符使两串相同
int edit(string s, string t) {
int n = s.size();
int m = t.size();
if (n == 0)
return m;
if (m == 0)
return n;
for (int i = 0; i <= n; i++)
d[i][0] = i;
for (int j = 0; j <= m; j++)
d[0][j] = j;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
if (s[i - 1] == t[j - 1])
d[i][j] = d[i - 1][j - 1];
else
d[i][j] =
min(d[i - 1][j - 1], min(d[i - 1][j], d[i][j - 1])) + 1;
}
return d[n][m];
}