区间dp【i】【j】记录区间【i,j】成回文串时不同对数
#include<algorithm> #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<vector> #define REP(i, n) for(int i=0; i<n; i++) #define FF(i, a, b) for(int i=a; i<b; i++) #define FD(i, a, b) for(int i=a; i>=b; i--) #define CLR(a, b) memset(a, b, sizeof(a)) #define PB push_back using namespace std; char h[1100]; int idx[1100]; int dp[1010][1010]; bool vis[1010][1010]; int N; int n, k; int dpf(int l, int r) { if (l >= r) return 0; if (vis[l][r]) return dp[l][r]; vis[l][r] = 1; int &ans = dp[l][r]; ans = dpf(l + 1, r - 1); if (h[l] != h[r]) ans += 2; return ans; } void input() { n = 0; N = 0; char c = getchar(); while (c != '\n') { N++; if (c <= 'z' && c >= 'a') h[n++] = c, idx[n - 1] = N; else if (c <= 'Z' && c >= 'A') h[n++] = c - 'A' + 'a', idx[n - 1] = N; c = getchar(); } h[n] = 0; } int main() { int nc = 1; while (~scanf("%d", &k)) { k *= 2; getchar(); input(); CLR(vis, 0); int ans, ansi; ans = -1; for (int L = n; L >= 1; L--) { for (int i = 0; i + L - 1 < n; i++) { int j = i + L - 1; if (dpf(i, j) <= k) { if (ans < idx[j] - idx[i] + 1) { ans = idx[j] - idx[i] + 1; ansi = idx[i]; } else if (ans == idx[j] - idx[i] + 1) ansi = min(ansi, idx[i]); } } } printf("Case %d: %d %d\n", nc++, ans, ansi); } }
本文介绍了一种使用区间动态规划解决回文串问题的方法。通过定义dp[i][j]来记录区间[i,j]形成回文串时的不同对数,并采用递归的方式进行状态转移,最终找到满足条件的最大子串长度及其起始位置。
368

被折叠的 条评论
为什么被折叠?



