CodeForces - 245H - Queries for Number of Palindromes

先上题目:

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, if t = 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.

Sample test(s)
input
caaaba
5
1 1
1 4
2 3
4 6
4 5
output
1
7
3
4
2
Note

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

 

  题意:给你一个字符串,q个查询,问你某个区间里面有多少个回文串。

  区间dp,需要三个数组: s[] 字符串;f[i][j] [i,j]是不是一个回文串;dp[i][j] [i,j]包含了多少个字符串。

  初始化:

  f[i][i]=1

  f[i][i-1]=1           //在判断偶数长度的回文串的时候需要使用

  dp[i][i]=1

  状态转移方程:   dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+f[i][j]

  为什么可以这样列方程?这需要说一下对字符串的操作:我们先判断短的字符串,然后再增长判断的长度,这样dp[i+1][j]、dp[i][j-1]和dp[i+1][j-1]在对dp[i][j]操作之前就已经处理完保存了处理以后的数据了。

 

上代码:

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #define MAX 5002
 4 using namespace std;
 5 
 6 char s[MAX];
 7 
 8 /*
 9     dp[i][j]: [i,j]中包含了多少个回文串
10     f[i][j]:  [i,j]是否是回文串
11 */
12 int dp[MAX][MAX];
13 int f[MAX][MAX];
14 
15 int main()
16 {
17     int q,a,b,l;
18     //freopen("data.txt","r",stdin);
19     while(scanf("%s",s+1)!=EOF){
20         memset(dp,0,sizeof(dp));
21         memset(f,0,sizeof(f));
22         l=strlen(s+1);
23         for(int i=1;i<=l;i++){
24                 /*初始化:
25                          f[i][i]=1   单个字母是一个回文串
26                          f[i][i-1]=1 考虑偶数个字母是一个回文串的时候的情况(状态转移的方向决定的)
27                          dp[i][i]=1   单个字母的时候[i,i]有一个回文串
28                 */
29                 f[i][i]=1;
30                 f[i][i-1]=1;
31                 dp[i][i]=1;
32         }
33         for(int le=2;le<=l;le++){
34             for(int i=1,j=le;j<=l;i++,j++){
35                 if(s[i]==s[j]){
36                    /*s[i]==s[j] &&  [i+1,j-1]也是回文串*/
37                    f[i][j]=f[i+1][j-1];
38                 }
39                 dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]+f[i][j];
40             }
41         }
42         scanf("%d",&q);
43         while(q--){
44             scanf("%d %d",&a,&b);
45             printf("%d\n",dp[a][b]);
46         }
47 
48     }
49     return 0;
50 }
245H

 

posted @ 2014-03-18 13:47  海拉鲁的林克  阅读(265)  评论(0编辑  收藏  举报