Description:
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.
#include<cstdio>
#include<cstring>
using namespace std;
const int L = 5010;
char s[L];
int dp[L][L],flag[L][L],q,len;
int C(int l,int r)
{
if(flag[l][r]) return 1;
return flag[l][r] = (s[l] == s[r])&&C(l + 1,r - 1);
}
int rec(int l,int r)
{
if(dp[l][r]) return dp[l][r];
if(l == r) return dp[l][r] = 1;
if(l == r - 1) return dp[l][r] = 2 + (s[l] == s[r]? 1 : 0);
return dp[l][r] = rec(l,r - 1) + rec(l + 1,r) - rec(l + 1,r - 1) + C(l,r);
}
void solve()
{
len = strlen(s + 1);
for(int i = 1;i <= len;++i)
{
dp[i][i] = flag[i][i] = 1;
if(s[i] == s[i+1]){
dp[i][i + 1] = 3;
flag[i][i + 1] = 1;
}
else
{
dp[i][i + 1] = 2;
flag[i][i + 1] = 0;
}
}
for(int k = 3;k <= len;++k)
{
int l = 1;
for(int r = k;r <= len;++r,++l)
{
dp[l][r] = dp[l][r - 1] + dp[l + 1][r] - dp[l + 1][r - 1] + C(l,r);
}
}
}
int main()
{
scanf("%s",s + 1);
scanf("%d",&q);
solve();
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d
",dp[l][r]);
}
return 0;
}