来源
本题dp思想
dp主要思想是:在同一类问题模型下,依赖于已经解决的简单问题基础上,用很小的代价获得更复杂一点的问题的解决方案。
有的题的DP是在下标上顺序性递推的,类似于dp[i]=dp[i-1]+something;
然而这道题的DP是在子串长度上的顺序性递推,而不是在下标上的顺序性递推。
过程
首先算出所有长度为2的子串的dp值,即所有的dp[i][i+1],然后长度依次从3,4,……递增到n,每一个区间从i到j的子串,他们的dp值意味着可否反转这一段的子串,dp=0不可翻转,dp=1可翻转。
对于长度为len的子串,左右下标分别为i和j
d p ( i , j ) = { 1 , if s t r [ i ] > s t r [ j ] 0 , if s t r [ i ] < s t r [ j ] d p ( i + 1 , j − 1 ) , if s t r [ i ] = s t r [ j ] dp_{(i,j)} = \begin{cases} 1, & \text{if } str[i] > str[j] \\ 0, & \text{if } str[i]<str[j] \\ dp_{(i+1,j-1)}, &\text{if } str[i]=str[j] \end{cases} dp(i,j)=⎩ ⎨ ⎧1,0,dp(i+1,j−1),if str[i]>str[j]if str[i]<str[j]if str[i]=str[j]
时间复杂度分析
该算法 O ( n 2 ) 预测暴力算法将会是 O ( n 3 ) 该算法O(n^2)预测暴力算法将会是O(n^3) 该算法O(n2)预测暴力算法将会是O(n3)
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
string str;
cin >> str;
int n = str.size();
// 初始化二维数组并默认值为0
vector<vector<int>> arr(n, vector<int>(n, 0));
// 长度为2的子串比较
for (int i = 0; i < n - 1; i++) {
arr[i][i + 1] = (str[i] > str[i + 1]);
}
// 长度 >= 3 的子串处理
for (int len = 3; len <= n; len++) {
for (int i = 0; i <= n - len; i++) {
int j = i + len - 1;
if (str[i] == str[j])
arr[i][j] = arr[i + 1][j - 1];
else
arr[i][j] = (str[i] > str[j]);
}
}
// 统计满足条件的子串对
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
count += arr[i][j];
}
}
cout << count << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
AI生成出来的代码:(同思路,简洁程度更)
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.size();
vector<vector<bool>> dp(n, vector<bool>(n, false));
for (int len = 2; len <= n; ++len) {
for (int i = 0; i + len - 1 < n; ++i) {
int j = i + len - 1;
if (s[i] > s[j]) {
dp[i][j] = true;
} else if (s[i] == s[j]) {
if (j - i >= 2) {
dp[i][j] = dp[i+1][j-1];
} else {
dp[i][j] = false;
}
}
// else s[i] < s[j], dp[i][j] remains false
}
}
int count = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (dp[i][j]) {
++count;
}
}
}
cout << count << endl;
return 0;
}
本文介绍了如何使用动态规划(DP)解决洛谷P9232题目中的字符串翻转问题,重点在于子串长度上的顺序性递推,通过比较子串内字符决定是否可以翻转。
1544

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



