codeforces 245H Queries for Number of Palindromes RK Hash + dp

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 qqueries, 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.

Examples
input
Copy
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».

 

 

大意:长度为N的字符串,Q个询问,询问某个区间中回文子串(连续)的数量

 

 

 

 

题解:

 

将字符串和反转串的RK hash值求出,这样可以O(1)判断两个子串是否相等。

f[i][j]表示[i,j]区间中回文子串的数量,可以以区间大小为阶段利用简单容斥来递推。

f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+([i,j]是回文串)

要[i,j]是回文串,只需在原串中求出前半部分的 hash 值,在反转串中求出后半串的 hash 值,判断是否相等即可。

 

tips:亲测O(N^2 logN)过不了,要预处理seed的幂次方

 

 1 /*
 2 Welcome Hacking
 3 Wish You High Rating
 4 */
 5 #include<iostream>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<ctime>
 9 #include<cstdlib>
10 #include<algorithm>
11 #include<cmath>
12 #include<string>
13 using namespace std;
14 int read(){
15     int xx=0,ff=1;char ch=getchar();
16     while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
17     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
18     return xx*ff;
19 }
20 const int seed[2]={13137,91},MOD=1000000007;
21 char s1[5010],s2[5010];
22 int H1[2][5010],H2[2][5010];
23 int N;
24 int pow_seed[2][5010];
25 void Hashing(int x){
26     for(int i=1;i<=N;i++){
27         H1[x][i]=(1LL*H1[x][i-1]*seed[x]+s1[i])%MOD;
28         H2[x][i]=(1LL*H2[x][i-1]*seed[x]+s2[i])%MOD;
29     }
30 }
31 int get_hash1(int x,int L,int R){
32     return ((H1[x][R]-1LL*H1[x][L-1]*pow_seed[x][R-L+1])%MOD+MOD)%MOD;
33 }
34 int get_hash2(int x,int L,int R){
35     return ((H2[x][R]-1LL*H2[x][L-1]*pow_seed[x][R-L+1])%MOD+MOD)%MOD;
36 }
37 inline int ref(int x)
38 {return N-x+1;}
39 inline bool judge(int L,int R){
40     if(L==R)
41         return 1;
42     int mid=(L+R)/2;
43     if((R-L+1)%2==0){
44         if(get_hash1(0,L,mid)==get_hash2(0,ref(R),ref(mid+1)))
45             if(get_hash1(1,L,mid)==get_hash2(1,ref(R),ref(mid+1)))
46                 return 1;
47     }
48     else{
49         if(get_hash1(0,L,mid)==get_hash2(0,ref(R),ref(mid)))
50             if(get_hash1(1,L,mid)==get_hash2(1,ref(R),ref(mid)))
51                 return 1;
52     }
53     return 0;
54 }
55 long long f[5010][5010];
56 int main(){
57     //freopen("in","r",stdin);
58     gets(s1+1);N=strlen(s1+1);
59     for(int i=1;i<=N;i++)
60         s2[i]=s1[ref(i)];
61     pow_seed[0][0]=pow_seed[1][0]=1;
62     for(int i=1;i<=N;i++){
63         pow_seed[0][i]=1LL*pow_seed[0][i-1]*seed[0]%MOD;
64         pow_seed[1][i]=1LL*pow_seed[1][i-1]*seed[1]%MOD;
65     }
66     Hashing(0);
67     Hashing(1);
68     for(int i=1;i<=N;i++)
69         f[i][i]=1;
70     for(int p=2;p<=N;p++)
71         for(int i=1;i<=N;i++){
72             int j=i+p-1;
73             if(j>N)
74                 break;
75             f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+judge(i,j);
76         }
77     /*for(int i=1;i<=N;i++){
78         for(int j=1;j<=N;j++)
79             printf("%I64d ",f[i][j]);
80         puts("");
81     }*/
82     for(int Q=read();Q;Q--){
83         int t1=read(),t2=read();
84         printf("%I64d\n",f[t1][t2]);
85     }
86     return 0;
87 }
View Code

 

 

 

 

 

posted @ 2018-03-15 16:57  咸鱼lzh  阅读(302)  评论(0编辑  收藏  举报