CF 245H. Queries for Number of Palindromes 区间dp

来源:互联网 发布:unity3d项目实战教程 编辑:程序博客网 时间:2024/06/05 19:27


H. Queries for Number of Palindromes
time limit per test
5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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, ift = t1t2... t|t| = t|t|t|t| - 1... t1.

Input

The first line contains string s (1 ≤ |s| ≤ 5000). The second line contains a single integer q (1 ≤ q ≤ 106) — the number of queries. Next q lines contain the queries. The i-th of these lines contains two space-separated integers li, ri (1 ≤ li ≤ ri ≤ |s|) — the description of the i-th query.

It is guaranteed that the given string consists only of lowercase English letters.

Output

Print q integers — the answers to the queries. Print the answers in the order, in which the queries are given in the input. Separate the printed numbers by whitespaces.

Examples
input
caaaba51 11 42 34 64 5
output
17342
Note

Consider the fourth query in the first test case. String s[4... 6] = «aba». Its palindrome substrings are: «a», «b», «a», «aba».



题意:给出一个字符串s(1 ≤ |s| ≤ 5000),还有q(1 ≤ q ≤ 106)个查询,每个查询输入一个区间,问区间内有多少回文子串(子串必须连续)

感觉不像是dp啊,就是数学计数问题。



关键思路:对于任意一个区间[le,ri],首先要判断是否能构成回文串,

 if(s[le]==s[ri]&& isPali(le+1,ri-1) ) pali[le][ri]=1;


然后就是统计[le,ri]内的回文串个数:

 dp[le][ri]=dp[le+1][ri]+dp[le][ri-1]-DP(le+1,ri-1)+pali[le][ri];

由于[le+1,ri]和[le,ri-1]内有重叠部分,故减去,容斥原理。




#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>using namespace std;#define all(x) (x).begin(), (x).end()#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])#define mem(a,x)  memset(a,x,sizeof a)#define ysk(x)  (1<<(x))typedef long long ll;typedef pair<int, int> pii;const int INF =0x3f3f3f3f;const int maxn=5000    ;char s[maxn+3];int dp[maxn+3][maxn+3],m,n;bool pali[maxn+3][maxn+3];bool isPali(int le ,int ri){    if(le>ri)  return true;    return pali[le][ri];}int DP(int le,int ri){    if(le>ri)  return 0;    return dp[le][ri];}void solve(){    n=strlen(s+1);    for(int i=1;i<=n;i++)    {        dp[i][i]=1;        pali[i][i]=1;    }    for(int add=1;add<n;add++)    {        for(int le=1;le+add<=n;le++)        {            int ri=le+add;            if(s[le]==s[ri]&& isPali(le+1,ri-1) ) pali[le][ri]=1;            dp[le][ri]=dp[le+1][ri]+dp[le][ri-1]-DP(le+1,ri-1)+pali[le][ri];        }    }}int main(){   std::ios::sync_with_stdio(false);   scanf("%s",s+1);   solve();   scanf("%d",&m);   int le,ri;   while(m--)   {       scanf("%d%d",&le,&ri);       printf("%d\n",dp[le][ri]);   }   return 0;}


0 0
原创粉丝点击