传送门

题目2 : 回文字符序列

时间限制:2000ms
单点时限:1000ms
内存限制:256MB

描述

给定字符串,求它的回文子序列个数。回文子序列反转字符顺序后仍然与原序列相同。例如字符串aba中,回文子序列为"a", "a", "aa", "b", "aba",共5个。内容相同位置不同的子序列算不同的子序列。

输入

第一行一个整数T,表示数据组数。之后是T组数据,每组数据为一行字符串。

输出

对于每组数据输出一行,格式为"Case #X: Y",X代表数据编号(从1开始),Y为答案。答案对100007取模。

数据范围

1 ≤ T ≤ 30

小数据

字符串长度 ≤ 25

大数据

字符串长度 ≤ 1000

样例输入
5
aba
abcbaddabcba
12111112351121
ccccccc
fdadfa
样例输出
Case #1: 5
Case #2: 277
Case #3: 1333
Case #4: 127
Case #5: 17

题解:

思路来自贲神

一开始看错了题,以为是算回文子串(要求连续),结果题目是算回文子序列(不一定要连续)。

故,用区间dp,搞了好久。。。晕死,最后用的是记忆化dp,没想到递推肿么搞。

看了网上的代码后,发现:我的思路还是有偏差。

递推的转移方程应该为:

if (s[i] == s[j])
dp[i][j] = (dp[i + ][j] + dp[i][j - ] + ) % mod;
else
dp[i][j] = (dp[i + ][j] + dp[i][j - ] - dp[i + ][j - ]) % mod;

结果:AC | NA    提交时间:2015-04-17 16:05:34

贴一份其他人ac的代码:

 #include <iostream>
#include <cstdio>
#include <cstring> using namespace std; const int maxn = ;
char s[maxn];
const int mod = ;
int dp[maxn][maxn]; int solve()
{
memset(dp, , sizeof(dp));
int n = strlen(s); for (int l = ; l <= n; ++l)
{
for (int i = ; i + l < n; ++i)
{
int j = i + l;
if (s[i] == s[j])
dp[i][j] = (dp[i + ][j] + dp[i][j - ] + ) % mod;
else
dp[i][j] = (dp[i + ][j] + dp[i][j - ] - dp[i + ][j - ]) % mod;
}
} return (dp[][n - ]%mod + mod)%mod;
} int main()
{
int T;
cin >> T;
for (int cas = ; cas <= T; ++cas)
{
cin >> s;
printf("Case #%d: %d\n", cas, solve());
}
return ;
}

再贴一发记忆化dp ac的代码:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std; #define mxn 200005
#define LL long long
#define MP make_pair
#define REP(i, a, b) for (int i = a; i <= b; ++i)
#define FOR(i, a, b) for (int i = a; i < b; ++i) #define mod 100007 int dp[][];
char s[]; int F(int l, int r) {
if (dp[l][r] != -) return dp[l][r];
if (l > r) return dp[l][r] = ;
if (l == r) return dp[l][r] = ;
int& ret = dp[l][r];
ret = (F(l + , r) + F(l, r - )) % mod;
if (s[l] == s[r]) ++ret;
else ret -= F(l + , r - );
ret = (ret + mod) % mod;
return ret;
} int main()
{
int cas = , t; scanf("%d", &t);
while (t--) {
memset(dp, -, sizeof(dp));
scanf("%s", s + );
int ans = F(, strlen(s + ));
printf("Case #%d: %d\n", ++cas, ans);
}
return ;
}

我的思路复杂度不好,T了

 #include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
#include <cmath> #define ll long long
int const N = ;
int const M = ;
int const INF = 0x7fffffff;
int const mod = ; using namespace std; int T,cnt;
int dp[N][N];
char s[N];
int l;
int ans; void ini()
{
scanf("%s",s+);
l=strlen(s+);
memset(dp,-,sizeof(dp));
} int dfs(int st,int en)
{
if(dp[st][en]!=-) return dp[st][en];
if(st>en){
return dp[st][en]=;
}
if(st==en){
return dp[st][en]=;
}
dp[st][en]=dfs(st,en-)+;
// printf(" st=%d en=%d dp=%d\n",st,en,dp[st][en]); int i;
for(i=st;i<en;i++){
if(s[i]==s[en])
dp[st][en]=(dp[st][en]+dfs(i+,en-)+)%mod;
}
return dp[st][en];
} void solve()
{
ans=dfs(,l);
} void out()
{
/*
int i,j;
for(i=1;i<=l;i++){
for(j=i;j<=l;j++){
printf(" i=%d j=%d dp=%d\n",i,j,dp[i][j]);
}
}*/
printf("Case #%d: %d\n",cnt,ans);
} int main()
{
//freopen("data.in","r",stdin);
scanf("%d",&T);
for(cnt=;cnt<=T;cnt++)
// while(T--)
//while(scanf("%d%d",&n,&m)!=EOF)
{
ini();
solve();
out();
} return ;
}

编程之美2015资格赛 题目2 : 回文字符序列 [ 区间dp ]的更多相关文章

  1. 编程之美2015 资格赛 hihocoder 题目2: 回文字符序列

    思路:暴力搜,用BFS的方式,生成每一种可能,再对每一种可能进行判断是否回文,进行统计.严重超时!计算一个25个字符的,大概要20多秒! #include <iostream> #incl ...

  2. HDU 4745 Two Rabbits ★(最长回文子序列:区间DP)

    题意 在一个圆环串中找一个最长的子序列,并且这个子序列是轴对称的. 思路 从对称轴上一点出发,向两个方向运动可以正好满足题意,并且可以证明如果抽选择的子环不是对称的话,其一定不是最长的. 倍长原序列, ...

  3. 合并回文子串(区间dp)

    链接:https://ac.nowcoder.com/acm/problem/13230来源:牛客网 题目描述 输入两个字符串A和B,合并成一个串C,属于A和B的字符在C中顺序保持不变.如" ...

  4. hdu4632 Palindrome subsequence 回文子序列个数 区间dp

    Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/ ...

  5. 便宜的回文串(区间DP)

    题目链接:便宜的回文串 这道题刚开始其实还是没有思路的.没办法,只能看题解了... 其实我们在思考问题时,考虑到一段串增或减时会改变它的长度,所以转移时会麻烦... 但其实不用考虑那么多的问题,我们只 ...

  6. [HIHO1323]回文字符串(区间dp)

    题目链接:http://hihocoder.com/problemset/problem/1323 思路:区间dp,按照区间长度枚举所有区间和区间的起始位置.这时也可获取到区间的末位,比对这两个字符是 ...

  7. hihocoder1323 回文字符串(区间dp)

    https://hihocoder.com/problemset/problem/1323 刚开始真没看出来这是一道dp题.. dp[i][j]表示i~j段修改成回文串所需的最少操作次数.然后根据s[ ...

  8. hihoCoser(#1149 : 回文字符序列)

    时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给定字符串,求它的回文子序列个数.回文子序列反转字符顺序后仍然与原序列相同.例如字符串aba中,回文子序列为"a& ...

  9. 【HIHOCODER 1323】回文字符串(区间DP)

    描述 给定一个字符串 S ,最少需要几次增删改操作可以把 S 变成一个回文字符串? 一次操作可以在任意位置插入一个字符,或者删除任意一个字符,或者把任意一个字符修改成任意其他字符. 输入 字符串 S. ...

随机推荐

  1. centos系统iptables使用帮助

    #如果只是想屏蔽IP的话“开放指定的端口”可以直接跳过.#屏蔽单个IP的命令是iptables -I INPUT -s 123.45.6.7 -j DROP#封整个段即从123.0.0.1到123.2 ...

  2. 我来解数独(附delphi源码)

    前段时间看到“69岁农民3天破解世界最难数独游戏”,然后在看了那个号称世界最难的数独题目之后,就打算抽空编程解决.今晚抽出一个晚上,大约四五个小时的时间,中间还间歇在clash of clans上造兵 ...

  3. codevs 6116 区间素数

     时间限制: 8 s  空间限制: 256000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 小明喜欢研究素数,他想统计两个自然数之间的素数个数,现在 ...

  4. 原创Couldn't read packet: Connection reset by peer 错误排查思路(推荐)

    作为一个运维 不是你懂多少知识才是你的价值 你有幸能遇到多少错误才是你的最大的价值 知识 你有我有大家有  错误我有你没有 这便是我的价值 我遇到一个错误 蛮难遇到的一个错误 所以想分享给大家 下面我 ...

  5. ChromiumWebBrowser禁止鼠标右键和拖动

    在屏蔽之前先查看namespace CefSharp.WinForms内的代码 public class ChromiumWebBrowser : Control, IWebBrowserIntern ...

  6. linux下C的建立、编译和运行 gcc (附上Windows下visual c++的用法)

    2019/6/24 1. 环境:window10下安装了MobaXterm,这里申请了阿里云的服务账号,可以直接使用linux系统,避免安装虚拟机等. 2. 判断linux下是否有GCC编译工具(我们 ...

  7. Logisim的使用

    准备 通过Logisim的官网下载适合你机器的Logisim的软件,启动Logisim应用程序(Logisim可能有点bug,如果程序运行诡异,可能内部已经奔溃,最好的解决方法是重新启动它). Log ...

  8. zabbix user-defined item

    1.user-defind item at:/etc/zabbix/zabbix_agent.conf format: UserParameter=<key>,<command> ...

  9. dinic网络流

    C - A Plug for UNIX POJ - 1087 You are in charge of setting up the press room for the inaugural meet ...

  10. Oracle 11G RAC 修改IP

    实验环境 类别 修改前 修改后 PUBLIC 172.18.4.182 rac1 192.168.56.10 rac1 172.18.4.184 rac2 192.168.56.20 rac2 PRI ...