「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
",dp[f[i].l-1][f[i].r-1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/LocaEtric/p/9615062.html