当前位置: 首页 > news >正文

编程之美2015资格赛 题目2 : 回文字符序列 [ 区间dp ]

传送门

题目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 + 1][j] + dp[i][j - 1] + 1) % mod;
else
    dp[i][j] = (dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]) % mod;

 

 

 

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

 

 

贴一份其他人ac的代码:

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 1100;
 8 char s[maxn];
 9 const int mod = 100007;
10 int dp[maxn][maxn];
11 
12 int solve()
13 {
14     memset(dp, 0, sizeof(dp));
15     int n = strlen(s);
16     
17     for (int l = 0; l <= n; ++l)
18     {
19         for (int i = 0; i + l < n; ++i)
20         {
21             int j = i + l;
22             if (s[i] == s[j])
23                 dp[i][j] = (dp[i + 1][j] + dp[i][j - 1] + 1) % mod;
24             else
25                 dp[i][j] = (dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1]) % mod;
26         }
27     }
28     
29     return (dp[0][n - 1]%mod + mod)%mod;
30 }
31 
32 int main()
33 {
34     int T;
35     cin >> T;
36     for (int cas = 1; cas <= T; ++cas)
37     {
38         cin >> s;
39         printf("Case #%d: %d\n", cas, solve());
40     }
41     return 0;
42 }
View Code

 

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

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <map>
 5 #include <algorithm>
 6 using namespace std;
 7 
 8 #define mxn 200005
 9 #define LL long long
10 #define MP make_pair
11 #define REP(i, a, b) for (int i = a; i <= b; ++i)
12 #define FOR(i, a, b) for (int i = a; i < b; ++i)
13 
14 #define mod 100007
15 
16 int dp[1005][1005];
17 char s[1005];
18 
19 int F(int l, int r) {
20     if (dp[l][r] != -1) return dp[l][r];
21     if (l > r) return dp[l][r] = 0;
22     if (l == r) return dp[l][r] = 1;
23     int& ret = dp[l][r];
24     ret = (F(l + 1, r) + F(l, r - 1)) % mod;
25     if (s[l] == s[r]) ++ret;
26     else ret -= F(l + 1, r - 1);
27     ret = (ret + mod) % mod;
28     return ret;
29 }
30 
31 int main()
32 {
33     int cas = 0, t;
34 
35     scanf("%d", &t);
36     while (t--) {
37         memset(dp, -1, sizeof(dp));
38         scanf("%s", s + 1);
39         int ans = F(1, strlen(s + 1));
40         printf("Case #%d: %d\n", ++cas, ans);
41     }
42     return 0;
43 }
View Code

 


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

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <stack>
 4 #include <vector>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <map>
 8 #include <string>
 9 #include <cmath>
10 
11 #define ll long long
12 int const N = 1005;
13 int const M = 205;
14 int const INF = 0x7fffffff;
15 int const mod = 100007;
16 
17 using namespace std;
18 
19 int T,cnt;
20 int dp[N][N];
21 char s[N];
22 int l;
23 int ans;
24 
25 void ini()
26 {
27     scanf("%s",s+1);
28     l=strlen(s+1);
29     memset(dp,-1,sizeof(dp));
30 }
31 
32 int dfs(int st,int en)
33 {
34     if(dp[st][en]!=-1) return dp[st][en];
35     if(st>en){
36         return dp[st][en]=0;
37     }
38     if(st==en){
39         return dp[st][en]=1;
40     }
41     dp[st][en]=dfs(st,en-1)+1;
42    // printf(" st=%d en=%d dp=%d\n",st,en,dp[st][en]);
43 
44     int i;
45     for(i=st;i<en;i++){
46         if(s[i]==s[en])
47             dp[st][en]=(dp[st][en]+dfs(i+1,en-1)+1)%mod;
48     }
49     return dp[st][en];
50 }
51 
52 void solve()
53 {
54     ans=dfs(1,l);
55 }
56 
57 void out()
58 {
59 /*
60     int i,j;
61     for(i=1;i<=l;i++){
62         for(j=i;j<=l;j++){
63             printf(" i=%d j=%d dp=%d\n",i,j,dp[i][j]);
64         }
65     }*/
66     printf("Case #%d: %d\n",cnt,ans);
67 }
68 
69 int main()
70 {
71     //freopen("data.in","r",stdin);
72     scanf("%d",&T);
73     for(cnt=1;cnt<=T;cnt++)
74    // while(T--)
75     //while(scanf("%d%d",&n,&m)!=EOF)
76     {
77         ini();
78         solve();
79         out();
80     }
81 
82     return 0;
83 }

 

转载于:https://www.cnblogs.com/njczy2010/p/4435240.html

相关文章:

  • StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
  • Java培训小结
  • Flume NG 学习笔记(六)Selector(复用与复制)测试
  • [开源]用MQL4实现MD5加密
  • 清除浮动
  • zabbix监控mysql主从状态
  • 大整数算法[12] 有符号乘法
  • 多线程(七)---多线程同步相关问题
  • java基础入门1到100的奇数求和
  • 清除Css中select的下拉箭头样式
  • android中webview携带cookie以及webview所加载网页中js调用java方法问题
  • 模拟 ZOJ 3878 Convert QWERTY to Dvorak
  • 【Java每日一题】20170322
  • JavaScript中的对象复制(Object Clone)
  • C#后台传入数据JS接收
  • 自己简单写的 事件订阅机制
  • CEF与代理
  • centos安装java运行环境jdk+tomcat
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • go append函数以及写入
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Linux Process Manage
  • nginx 负载服务器优化
  • SOFAMosn配置模型
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • supervisor 永不挂掉的进程 安装以及使用
  • 服务器从安装到部署全过程(二)
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • FaaS 的简单实践
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • #android不同版本废弃api,新api。
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (八)c52学习之旅-中断实验
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (多级缓存)缓存同步
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (六)Hibernate的二级缓存
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (一)VirtualBox安装增强功能
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET/C# 的字符串暂存池
  • .NET命令行(CLI)常用命令
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .Net组件程序设计之线程、并发管理(一)
  • /etc/sudoers (root权限管理)
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [BROADCASTING]tensor的扩散机制
  • [C++] new和delete
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [ERROR] Plugin 'InnoDB' init function returned error
  • [flask]http请求//获取请求头信息+客户端信息
  • [hdu1561] The more, The Better 【树形DP】
  • [IE技巧] 如何关闭Windows Server版IE的安全限制