DP-Again Palindrome - UVA - 10617

DP-Again Palindrome - UVA - 10617

题意:
给 定 一 个 长 度 为 n 的 字 符 串 , 删 除 一 些 字 符 ( 包 括 0 个 ) , 使 得 其 成 为 回 文 串 , 问 共 有 多 少 种 删 法 。 本 质 上 是 问 , 有 多 少 个 子 串 是 回 文 的 。 T 组 测 试 用 例 。 给定一个长度为n的字符串,删除一些字符(包括0个),使得其成为回文串,问共有多少种删法。\\本质上是问,有多少个子串是回文的。\\T组测试用例。 n(0)使T

Sample Input:
3
BAOBAB
AAAA
ABA

Sample Output:
22
15
5

数据范围:
T ∈ [ 1 , 15 ] , n ∈ [ 1 , 60 ] 。 T i m e   l i m i t : 3000 m s T∈[1,15],n∈[1,60]。\\Time\ limit:3000 ms T[1,15]n[1,60]Time limit3000ms

题解:

设 d p [ i ] [ j ] 表 示 区 间 为 [ i , j ] 的 字 符 串 所 包 含 的 回 文 子 串 的 数 量 。 状 态 转 移 方 程 : ① 、 s [ i ] = s [ j ] 时 , d p [ i ] [ j ] = d p [ i + 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i + 1 ] [ j − 1 ] + ( d p [ i + 1 ] [ j − 1 ] + 1 ) ② 、 s [ i ] ≠ s [ j ] 时 , d p [ i ] [ j ] = d p [ i + 1 ] [ j ] + d p [ i ] [ j − 1 ] − d p [ i + 1 ] [ j − 1 ] 。   理 解 : 对 第 二 种 情 况 , 缩 小 问 题 规 模 , 减 去 的 是 区 间 [ i + 1 , j ] 与 [ i , j − 1 ] 重 叠 部 分 , 类 似 于 容 斥 ; 而 第 一 种 情 况 , 由 于 s [ i ] = s [ j ] , 那 么 这 两 个 字 符 可 以 加 在 [ i + 1 , j − 1 ] 内 的 任 意 回 文 子 串 两 端 构 成 新 的 回 文 串 , 数 量 就 额 外 增 多 了 d p [ i + 1 ] [ j − 1 ] 个 , 再 加 上 [ i , j ] 本 身 算 一 个 回 文 串 , ① 就 在 ② 的 基 础 上 增 加 了 d p [ i + 1 ] [ j − 1 ] + 1 个 。 设dp[i][j]表示区间为[i,j]的字符串所包含的回文子串的数量。\\状态转移方程:\\①、s[i]=s[j]时,dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+(dp[i+1][j-1]+1)\\②、s[i]≠s[j]时,dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]。\\ \ \\理解:对第二种情况,缩小问题规模,减去的是区间[i+1,j]与[i,j-1]重叠部分,类似于容斥;\\而第一种情况,由于s[i]=s[j],那么这两个字符可以加在[i+1,j-1]内的任意回文子串两端构成新的回文串,\\数量就额外增多了dp[i+1][j-1]个,再加上[i,j]本身算一个回文串,①就在②的基础上增加了dp[i+1][j-1]+1个。 dp[i][j][i,j]:s[i]=s[j]dp[i][j]=dp[i+1][j]+dp[i][j1]dp[i+1][j1]+(dp[i+1][j1]+1)s[i]=s[j]dp[i][j]=dp[i+1][j]+dp[i][j1]dp[i+1][j1] [i+1,j][i,j1]s[i]=s[j][i+1,j1]dp[i+1][j1][i,j]dp[i+1][j1]+1

具体落实:

① 、 由 于 递 推 是 从 短 推 长 , 所 以 要 先 把 短 的 计 算 好 。 先 预 处 理 长 度 为 1 的 回 文 串 d p [ i ] [ i ] = 1 。 ② 、 按 长 度 处 理 , 长 度 i 从 [ 2 , n ] , 根 据 递 推 关 系 式 , 求 出 每 个 长 度 区 间 下 的 回 文 子 串 个 数 。 ①、由于递推是从短推长,所以要先把短的计算好。先预处理长度为1的回文串dp[i][i]=1。\\②、按长度处理,长度i从[2,n],根据递推关系式,求出每个长度区间下的回文子串个数。 1dp[i][i]=1i[2,n]

注意:

字 符 串 的 长 度 最 大 达 到 60 , 极 端 情 况 下 共 有 约 2 60 种 子 串 , 因 此 d p 数 组 类 型 取 l o n g   l o n g 。 字符串的长度最大达到60,极端情况下共有约2^{60}种子串,因此dp数组类型取long\ long。 60260dplong long


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
const int N=65;
char s[N];
int T;
ll dp[N][N];

int main ()
{
    cin>>T;
    while(T--)
    {
        scanf("%s",s+1);
        int n=strlen(s+1);

        for(int i=1;i<=n;i++) dp[i][i]=1;

        for(int i=2;i<=n;i++)
            for(int j=1,k=i;k<=n;j++,k++)
            {
                dp[j][k]=dp[j][k-1]+dp[j+1][k]-dp[j+1][k-1];
                if(s[j]==s[k]) dp[j][k]+=dp[j+1][k-1]+1;
            }

        printf("%lld\n",dp[1][n]);
    }

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值