目录
- 数字三角形
- 最长上升子序列
- 最长公共子序列
- 最短编辑距离
- 编辑距离
数字三角形
const int N = 510, INF = 0x3f3f3f3f;
int n, m[N][N], dp[N][N];
int main()
{cin >> n;for(int i = 0; i < n; ++i)for(int j = 0; j <= i; ++j)cin >> m[i][j];for(int i = 0; i < N; ++i)for(int j = 0; j < N; ++j)dp[i][j] = -INF;dp[0][0] = m[0][0];for(int i = 1; i < n; ++i){for(int j = 0; j <= i; ++j){if(j == 0) dp[i][j] = dp[i - 1][j] + m[i][j];elsedp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + m[i][j];}}int ret = -0x3f3f3f3f;for(int j = 0; j < n; ++j)ret = max(ret, dp[n - 1][j]);cout << ret;return 0;
}
最长上升子序列
const int N = 1010, INF = 0x3f3f3f3f;
int n, a[N], dp[N];
int main()
{cin >> n;for(int i = 0; i < n; ++i)cin >> a[i];fill(dp, dp + N, 1);int ret = 1;for(int i = 1; i < n; ++i){for(int j = 0; j < i; ++j){if(a[i] > a[j])dp[i] = max(dp[i], dp[j] + 1);}ret = max(ret, dp[i]);}cout << ret;return 0;
}
最长公共子序列
dp[i][j]:A中前 i 位的所有子序列(含i或不含i),B中前 j 位的所有子序列(含j或不含j),中的最长公共子序列的长度- 根据 i j 位置的情乱进行讨论
- 针对不同情况中的重复部分的处理,这里是取最大值所以不影响
const int N = 1010;
int n, m, dp[N][N];
string s1, s2;int main()
{cin >> n >> m;cin >> s1 >> s2;s1 = " " + s1;s2 = " " + s2;for(int i = 1; i <= n; ++i){for(int j = 1; j <= m; ++j){if(s1[i] == s2[j])dp[i][j] = dp[i - 1][j - 1] + 1;elsedp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);}}cout << dp[n][m];return 0;
}
最短编辑距离
dp[i][j]:将A中1-i 改为B中1-j 的所有方法中,编辑最少的次数- 考虑最后一个位置,即第 i 位置 和 第 j 位置
- 初始化:
dp[i][0] = dp[0][i] = i;
const int N = 1010;
int n, m, dp[N][N];
string s1, s2;int main()
{cin >> n >> s1;cin >> m >> s2;s1 = " " + s1;s2 = " " + s2;for(int i = 1; i < N; ++i)dp[i][0] = dp[0][i] = i;for(int i = 1; i <= n; ++i){for(int j = 1; j <= m; ++j){dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;if(s1[i] != s2[j])dp[i][j] = min(dp[i][j], dp[i - 1][j -1] + 1);elsedp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);}}cout << dp[n][m];return 0;
}
编辑距离
const int N = 1010, LEN = 15;
int n, m, dp[LEN][LEN];
string s[N];
int edit_step(string s1, string s2)
{int n1 = s1.size(), n2 = s2.size();for(int i = 1; i <= n1; ++i)dp[i][0] = i;for(int i = 1; i <= n2; ++i)dp[0][i] = i;for(int i = 1; i <= n1; ++i){for(int j = 1; j <= n2; ++j){dp[i][j] = min(dp[i - 1][j], dp[i][j -1]) + 1;if(s1[i - 1] != s2[j - 1])dp[i][j] = min(dp[i][j], dp[i - 1][j - 1] + 1);elsedp[i][j] = min(dp[i][j], dp[i - 1][j - 1]);}}return dp[n1][n2];
}int main()
{cin >> n >> m;for(int i = 1; i <= n; ++i)cin >> s[i];while(m--){string tmp;int bar;cin >> tmp >> bar;int cnt = 0;for(int i = 1; i <= n; ++i)if(edit_step(tmp, s[i]) <= bar)cnt++;cout << cnt << endl;}return 0;
}