CodeForces - 245H Queries for Number of Palindromes

Posted on 2021-12-27 20:22  Capterlliar  阅读(32)  评论(0编辑  收藏  举报

题意:给定一个字符串,求区间[l,r]内有多少回文子串。

解:回文杀我。区间dp++

首先这玩意不能像前缀和一样[l,r]=[1,r]-[1,l-1]。

那就直接设dp[i][j]为[i,j]中回文子串的数量。

考虑拿小的拼大的。如果两端不等,

dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];

如果相等在此基础上加一。有空补补容斥原理。

然后是遍历的顺序。区间dp从小区间到大区间,这题因为只有相邻两个之间可以谈转移,所以两重循环就够了。区间长度为2的时候特判一下,因为vis[i+1][j-1]会没有orz

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 5005
#define eps 0.00000001
#define inf 0x3f3f3f3f
#define mod 1000000007
//#define int long long
char s[maxx];
int dp[maxx][maxx]={0};
int vis[maxx][maxx]={0};
signed main() {
    scanf("%s",s+1);
    int n=strlen(s+1);
    for(int i=1;i<=n;i++){
        dp[i][i]=1;
        vis[i][i]=1;
    }
    for(int len=2;len<=n;len++){
        for(int i=1;i<=n-len+1;i++){
            int j=i+len-1;
            dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1];
            if((len!=2&&vis[i+1][j-1]&&s[i]==s[j])||(len==2&&s[i]==s[j])){
                vis[i][j]=1;
                dp[i][j]++;
            }
        }
    }
    int q;
    scanf("%d",&q);
    while(q--){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",dp[l][r]);
    }
    return 0;
}
View Code