#include<iostream> #include<stdio.h> #include<string.h> using namespace std; int dp[2][5005];//用滚动数组防止空间溢出 char s[5005],e[5005];//e为s的逆序数组 int main() { int n; scanf("%d",&n); scanf("%s",s); for(int i=0;i<n;i++) { e[i]=s[n-1-i]; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { dp[i%2][j]=max(dp[(i-1)%2][j],dp[i%2][j-1]); if(s[i-1]==e[j-1])//由于数组下标是从0开始,所以用s[i-1]和e[j-1]来判断 dp[i%2][j]=max(dp[i%2][j],dp[(i-1)%2][j-1]+1); } } int ans=n-dp[n%2][n]; printf("%d",ans); return 0; }代码解释
时间: 2023-12-31 10:04:19 浏览: 111
这段代码是一个用于求字符串最长回文子序列的动态规划算法。下面是详细的代码解释:
1. 首先定义了一个大小为2*5005的二维数组dp,用来存储中间状态。
2. 然后读入了一个整数n,表示字符串的长度,再读入一个字符串s。
3. 接着,定义了一个字符数组e,用来存储字符串s的逆序数组。
4. 然后,使用双重循环遍历整个字符串s和e,计算dp数组的值。其中,dp[i%2][j]表示前i个字符和前j个字符所组成的两个子串的最长公共子序列的长度。由于dp数组是一个滚动数组,因此使用i%2来作为行下标,可以避免空间溢出。
5. 在计算dp数组时,首先将dp[i%2][j]的值设为dp[(i-1)%2][j]和dp[i%2][j-1]中的较大值,表示当前子串的最长公共子序列长度至少等于前一个子串和当前子串的最长公共子序列长度中的较大值。
6. 接着,判断s[i-1]和e[j-1]是否相等,如果相等,则将dp[i%2][j]的值更新为dp[(i-1)%2][j-1]+1,表示当前子串的最长公共子序列长度可以在前一个子串和当前子串的最长公共子序列长度中加上1得到。
7. 最后,计算出最长回文子序列的长度,即字符串长度减去dp[n%2][n]的值,并输出结果。
总之,这段代码是一种基于动态规划的求解字符串最长回文子序列问题的算法,其时间复杂度为O(n^2),空间复杂度为O(n)。
相关问题
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<iostream> #include<algorithm> #include<map> #include<stack> #include<queue> #include<vector> #include<set> #include<string> #define dd double #define ll long long dd PI = acos(-1); using namespace std; const ll MAXN = 1e5 + 5; const ll INF = 1e9 + 5; ll n; struct node { ll x, y; }s[5000]; ll dp[MAXN] = { 0 }; int main() { //ios::sync_with_stdio(false); ll n, m; cin >> n >> m; for (ll i = 1; i <= n; i++) { cin >> s[i].x >> s[i].y; } for (ll i = 1; i <= n; i++) { for (ll j = m; j >= s[i].x; j--) { dp[j] = max(dp[j], dp[j - s[i].x] + s[i].y); } } cout << dp[m] << endl; }
这是一段动态规划求解背包问题的代码,用来求解一个容量为m的背包能够装下的最大价值。具体实现过程为:
1. 定义一个结构体node,用来存储物品的重量和价值。
2. 读入物品数量n和背包容量m,然后读入每个物品的重量和价值。
3. 使用二重循环,遍历每一个物品,然后从大到小枚举背包容量j,更新dp[j]的值,表示容量为j的背包能够装下的最大价值。
4. 最后输出dp[m]的值,即容量为m的背包能够装下的最大价值。
值得注意的是,这段代码中还定义了一些常量和宏定义,如MAXN、INF等,以及一些头文件和命名空间的使用。
#include<math.h> #include<algorithm> #include<time.h> #include<stdlib.h> #include<iostream> #include<string.h> #include<map> #include<list> #include<string> #include<queue> #include<set> #include<vector> #include<stack> #include<limits> #define re register #define iosgo() std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); #define run(i,n) for (int i = 1; i <= n; i++) #define cin std::cin #define cout std::cout #define ll long long #define endl "\n" using namespace std; typedef pair<int, int>pll; const int N = 2e6 + 10; pll c[N]; int h[150][150]; int x[N], y[N], dp[N], ss[N]; int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } signed main() { string a; cin >> a; string b; cin >> b; if (a[0] == '0' || b[0] == '0') { cout << "0\n"; return 0; } int lena = a.length(); int lenb = b.length(); for (int i = 0; i < lena; i++) { x[i] = a[i] - '0'; } for (int i = 0; i < lenb; i++) { y[i] = b[i] - '0'; } int len = lena + lenb - 1; int r = 0; while (r < lenb) { for (int i = r, j = 0; i < lena + r; i++, j++) { ss[i] += x[j] * y[r]; } r++; } for (int i = len; i > 0; i--) { if (ss[i] >= 10) { ss[i - 1] += ss[i] / 10; ss[i] %= 10; } } for (int i = 0; i < len; i++) { cout << ss[i]; } }
这段代码是一个实现两个大整数相乘的程序。代码首先读取两个大整数a和b,然后将其转换为整型数组x和y。接下来,代码计算两个整数的乘积,并将结果存储在数组ss中。最后,代码将结果输出。
注意,这段代码没有考虑负数的情况,且对于较大的整数可能会导致溢出。如果需要处理更大的整数,可以考虑使用其他大数库或算法来实现。
阅读全文