1 条题解
-
0
自动搬运
来自洛谷,原作者为

zhlzt
Light in the eyes.搬运于
2025-08-24 22:46:36,当前版本为作者最后更新于2023-05-20 08:34:36,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
区间 DP 做法
其实要满足 ,就相当于判断翻转后的区间是否比原来小,假如翻转的区间为 ,则翻转前后的区间数值是这样的:
$$a_{i}~~a_{i+1}~~a_{i+2}~~\cdots ~~a_{j-2}~~a_{j-1}~~a_{j} $$$$a_{j}~~a_{j-1}~~a_{j-2}~~\cdots ~~a_{i+2}~~a_{i+1}~~a_{i} $$设双指针 。设 表示翻转的区间为 时是否满足条件。 有如下判断方法(可参照上图理解):
- 若 ,说明区间 为回文串,翻转前后相等,,退出判断。
- 若 ,则当前判断的区间 翻转后的最高位较大,,退出判断。
- 若 ,则当前判断的区间 翻转后的最高位较小,,退出判断。
- 若 ,则 对 的值没有影响,将双指针指向的区间 缩小到 ,即执行 。
如果像上述做法暴力判断的话,复杂度最差为 ,但经过整合即可得到:
- 若 ,则 。
- 若 ,则 。
- 若 ,则 。
这就是区间 DP,复杂度为 。
代码实现
#include<bits/stdc++.h> using namespace std; const int maxn=5010; char s[maxn]; int dp[maxn][maxn]; int main(){ scanf("%s",s); int n=strlen(s),ans=0; for(int i=0;i<n;i++) dp[i][i]=0; for(int i=0;i<n-1;i++) dp[i][i+1]=(s[i]>s[i+1]); // 初始值 for(int len=3;len<=n;len++){ for(int i=0;i<n-len+1;i++){ int j=i+len-1; if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]; else if(s[i]>s[j]) dp[i][j]=1; } } for(int i=0;i<n;i++){ for(int j=i;j<n;j++) ans+=dp[i][j]; } //求总数 printf("%d\n",ans); return 0; }
- 1
信息
- ID
- 8667
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者