zoukankan      html  css  js  c++  java
  • 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
    ",f[t1][t2]);
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    对文件上传使用表单验证
    文件上传
    自定义验证器
    WTForms常用的验证器
    Eclipse自动补全+常用快捷键
    JNI笔记
    cocos2d 2.2.6 win7下的配置
    cocos2d 3.6 win7下的配置
    python--文件删除、判断目录存在、字符串替换
    只是一个文件节点类为了项目的数据处理
  • 原文地址:https://www.cnblogs.com/lzhAFO/p/8574546.html
Copyright © 2011-2022 走看看