題意:給出長度不超過50000的字符串,詢問區間
思路:因爲字符串長度比較長,首先我們要解決的就是判斷
這個可以遞推得到。
設p[l][r]爲起始位置爲l,結束位置爲r的子串是否是迴文串。1表示是,0表示不是
遞推方程爲:
邊界條件是
統計迴文子串同樣可以遞推得到
設dp[l][r]爲其實位置爲l,結束位置爲r的子串中含有的迴文子串的個數。
遞推方程爲:
邊界條件是
整體的算法的複雜度就是
代碼如下:
#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;
}