CF 245H Queries for Number of Palindromes

題意:給出長度不超過50000的字符串,詢問區間[l,r]  內有多少迴文子串。
思路:因爲字符串長度比較長,首先我們要解決的就是判斷s l ...s r   是不是迴文字符串。
這個可以遞推得到。
設p[l][r]爲起始位置爲l,結束位置爲r的子串是否是迴文串。1表示是,0表示不是
遞推方程爲:

p[l][r]=1p[l+1][r1]=1s l =s r  

邊界條件是
p[l][l]=p[l][l+1]=1 

統計迴文子串同樣可以遞推得到
設dp[l][r]爲其實位置爲l,結束位置爲r的子串中含有的迴文子串的個數。
遞推方程爲:
dp[l][r]=dp[l+1][r]+dp[l][r1]dp[l+1][r1]+p[l][r] 

邊界條件是
dp[l][l]=dp[l][l+1]=1 

整體的算法的複雜度就是Θ(n 2 ) 
代碼如下:
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

char s[5010];
int p[5010][5010],dp[5010][5010];

int pail(int l, int r)
{
    if(p[l][r] >= 0)
        return p[l][r];
    if(l >= r)
        return p[l][r] = 1;
    if(s[l] == s[r] && pail(l+1,r-1))
        return p[l][r] = 1;
    else
        return p[l][r] = 0;
}

int sum(int l, int r)
{
    if(dp[l][r] >= 0)
        return dp[l][r];
    if(l == r)
        return dp[l][r] = 1;
    if(l > r)
        return dp[l][r] = 0;
    else
        return dp[l][r] = sum(l,r-1) + sum(l+1,r) - sum(l+1,r-1) + pail(l,r);
}



int main(void)
{
    //freopen("input.txt","r",stdin);
    int T;
    scanf("%s",s);
    scanf("%d",&T);
    memset(p,-1,sizeof(p));
    memset(dp,-1,sizeof(dp));
    for(int i = 0; i < T; ++i){
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%d\n",sum(--l,--r));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章