HDU 4632 Palindrome subsequence & FJUT3681 回文子序列种类数(回文子序列个数/回文子序列种数 容斥 + 区间DP)题解
题意1:问你一个串有几个不连续子序列(相同字母不同位置视为两个)
题意2:问你一个串有几种不连续子序列(相同字母不同位置视为一个,空串视为一个子序列)
思路1:由容斥可知当两个边界字母相同时 dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1] + dp[i + 1][j - 1] + 1;当两个字母不同时 dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]。然后区间DP即可
思路2:由思路1我们能大致知道怎么做,显然两边界字母不一样时情况是一样的。当两边字母一样时,那么就要判断中间的重复情况。
我们设l和r,表示i + 1 ~ j - 1里最左边的s[i]字母和最右边的s[i]字母
当 l == r 那么就只有一个相同字母,dp[i][j] = dp[i + 1][j - 1] + dp[i + 1][j - 1] + 1,答案为中间部分 + 中间加上两边界 + s[i]s[j]串
当 l > r,没有这个字母,dp[i][j] = dp[i + 1][j - 1] + dp[i + 1][j - 1] + 2,答案为中间部分 + 中间加上两边界 + s[i]s[j]串 + s[i]
当l < r,说明至少有两个字母,dp[i][j] = dp[i + 1][j - 1] + dp[i + 1][j - 1] - dp[l + 1][r - 1],答案为中间部分 + 中间加上两边界 - (l,r)区间内种数,因为这里面的和s[l],s[r]组成的串和s[i],s[j]重复
代码1:
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1e3 + ;
const ll MOD = 1e4 + ;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn]; //i到j种数
char s[maxn];
int main(){
int t, ca = ;
scanf("%d", &t);
while(t--){
scanf("%s", s + );
int n = strlen(s + );
for(int i = ; i <= n; i++){
dp[i][i] = ;
}
for(int len = ; len <= n; len++){
for(int i = ; i + len - <= n; i++){
int j = i + len - ;
if(s[i] == s[j]){
dp[i][j] = dp[i + ][j] + dp[i][j - ] + ;
}
else{
dp[i][j] = dp[i + ][j] + dp[i][j - ] - dp[i + ][j - ];
}
dp[i][j] = (dp[i][j] + MOD) % MOD;
}
}
printf("Case %d: %d\n", ca++, dp[][n]);
}
return ;
}
代码2:
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1e3 + ;
const ll MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
ll dp[maxn][maxn]; //i到j种数
char s[maxn];
int main(){
int t, ca = , n;
scanf("%d", &t);
while(t--){
scanf("%s", s + );
int n = strlen(s + );
for(int i = ; i <= n; i++){
dp[i][i] = ;
}
for(int len = ; len <= n; len++){
for(int i = ; i + len - <= n; i++){
int j = i + len - ;
if(s[i] == s[j]){
int l = i + , r = j - ;
while(s[l] != s[i] && l <= r) l++;
while(s[r] != s[i] && l <= r) r--;
if(l > r){
dp[i][j] = dp[i + ][j - ] + dp[i + ][j - ] + ;
}
else if(l == r){
dp[i][j] = dp[i + ][j - ] + dp[i + ][j - ] + ;
}
else{
dp[i][j] = dp[i + ][j - ] + dp[i + ][j - ] - dp[l + ][r - ];
}
}
else{
dp[i][j] = dp[i + ][j] + dp[i][j - ] - dp[i + ][j - ];
}
}
}
printf("Case %d: %lld\n", ca++, dp[][n]);
}
return ;
}
HDU 4632 Palindrome subsequence & FJUT3681 回文子序列种类数(回文子序列个数/回文子序列种数 容斥 + 区间DP)题解的更多相关文章
- HDU 4632 Palindrome subsequence(区间dp,回文串,字符处理)
题目 参考自博客:http://blog.csdn.net/u011498819/article/details/38356675 题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. ...
- HDU 4632 Palindrome subsequence (区间DP)
Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65535 K (Java/ ...
- HDU 4632 Palindrome subsequence (区间DP)
题意 给定一个字符串,问有多少个回文子串(两个子串可以一样). 思路 注意到任意一个回文子序列收尾两个字符一定是相同的,于是可以区间dp,用dp[i][j]表示原字符串中[i,j]位置中出现的回文子序 ...
- HDU 4632 Palindrome subsequence (2013多校4 1001 DP)
Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65535 K (Java/ ...
- HDU 4632 Palindrome subsequence(区间dp)
Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65535 K (Java/ ...
- HDU 4632 Palindrome subsequence(区间DP求回文子序列数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632 题目大意:给你若干个字符串,回答每个字符串有多少个回文子序列(可以不连续的子串).解题思路: 设 ...
- hdu 4632 Palindrome subsequence
http://acm.hdu.edu.cn/showproblem.php?pid=4632 简单DP 代码: #include<iostream> #include<cstdio& ...
- HDU 4632 Palindrome subsequence(DP)
题目链接 做的我很无奈,当时思路很乱,慌乱之中,起了一个想法,可以做,但是需要优化.尼玛,思路跑偏了,自己挖个坑,封榜之后,才从坑里出来,过的队那么多,开始的时候过的那么快,应该就不是用这种扯淡方法做 ...
- 【HDU】4632 Palindrome subsequence(回文子串的个数)
思路:设dp[i][j] 为i到j内回文子串的个数.先枚举所有字符串区间.再依据容斥原理. 那么状态转移方程为 dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+ ...
随机推荐
- executing in nfs will not generate core dump file
最近遇到了一个奇怪的问题. linux系统的pc搭建nfs server,开发板作为nfs client,开发板中全程root权限操作,执行的程序放到 nfs server 中 exports 出的目 ...
- 水题 J
一张CT扫描的灰度图像可以用一个N*N(0 < N <= 100)的矩阵描述,矩阵上的每个点对应一个灰度值(整数),其取值范围是0-255.我们假设给定的图像中有且只有一个肿瘤.在图上监测 ...
- DX9 空间坐标变换示例代码
// @time 2012.3.25 // @author jadeshu #include <Windows.h> #include <d3d9.h> #include &l ...
- Python全栈-day12-day13-函数4
1.迭代器 1)定义:迭代取值的工具 2)优缺点 优点 a.提供一种不依赖索引取值的方法 b.同时一时刻内存在存在的值只有一个,更加省内存 缺点 a.取值麻烦,只能通过next方法一个一个地往后取 b ...
- Nginx技术研究系列3-OpenResty安装配置
上两篇中介绍了: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 发现,应该加一篇OpenResty的安装部署说明,方便大家按图索骥 ...
- 【Hive学习之四】Hive 案例
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 apache-hive-3.1.1 ...
- django 常用方法总结 < 手写分页-上传头像-redis缓存,排行 ...>
1.不使用自带模块<Paginator>的手写分页功能views.pydef post_list(request): page = request.GET.get('page', 1) # ...
- loadRunner手动关联,通过 web_reg_save_param()函数
Action() { //<B>sign up now</B></A> /* web_reg_save_param_regexp( ...
- 51Nod 1072 威佐夫游戏
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1072 有2堆石子.A B两个人轮流拿,A先拿.每次可以从一堆 ...
- spark与kafka集成进行实时 nginx代理 这种sdk埋点 原生日志实时解析 处理
日志格式202.108.16.254^A1546795482.600^A/cntv.gif?appId=3&areaId=8213&srcContId=2535575&area ...