「Codeforces」245H Queries for Number of Palindromes (区间dp)

题意:原题在这

 

You've got a string s = s1s2... s|s| of length |s|, consisting of lowercase English letters. There also are q queries, each query is described by two integers li, ri (1 ≤ li ≤ ri ≤ |s|). The answer to the query is the number of substrings of string s[li... ri], which are palindromes.

String s[l... r] = slsl + 1... sr (1 ≤ l ≤ r ≤ |s|) is a substring of string s = s1s2... s|s|.

String t is called a palindrome, if it reads the same from left to right and from right to left. Formally, if t = t1t2... t|t| = t|t|t|t| - 1... t1.

给定一个字符串,q个询问,每个询问这个区间内有多少个回文串

 

做法:(详见行内注释)

定义vis[i][j]表示是不是回文串;
dp[i][j]为i到j的回文串总数


初始化一个:

    1.自己是回文串
    2.相邻的是回文串

再用can(x,y)递归判断vis[x][y]其他情况:

bool can(int x,int y)
{
    if (vis[x][y]) return true;
    else return vis[x][y]=(s[x]==s[y])&&(can(x+1,y-1));
}

 

 

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 99999999999
#define maxn 1000005
using namespace std;
string s;
int q,cnt,len;
bool vis[5005][5005];//vis[i][j]表示是否为回文串
int dp[5005][5005];//dp[i][j]表示回文子串数量

struct description
{
    int l,r;
}f[maxn];

bool can(int x,int y)
{
    if (vis[x][y]) return true;
    else return vis[x][y]=(s[x]==s[y])&&(can(x+1,y-1));
}

int main()
{
    cin>>s;
    len=s.size();
    //初始化
    memset(dp,0,sizeof(dp));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<=len;i++)//自己是回文串
    {
        vis[i][i]=1;
        dp[i][i]=1;
    } 
    for(int i=0;i<len;i++)//相邻的也是
    {
        if(s[i]==s[i+1])
        {
            vis[i][i+1]=1;
            dp[i][i+1]=3;
        }
        else dp[i][i+1]=2;
    }

    for(int k=2;k<len;k++)
    {
        int l=0;
        for(int r=k;r<len;r++)
        {
            dp[l][r]=dp[l+1][r]+dp[l][r-1]-dp[l+1][r-1];
            if (can(l,r)) dp[l][r]++;
            l++;
        }
    }

    cin>>q;
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&f[i].l,&f[i].r);
        // cin>>f[i].l>>f[i].r;
        // cout<<dp[f[i].l-1][f[i].r-1]<<endl;
        printf("%d\n",dp[f[i].l-1][f[i].r-1]);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/LocaEtric/p/9615062.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值