• acdream 1019: Palindrome 字符串多项式取Hash值


    1019: Palindrome

    Time Limit: 1 Sec  Memory Limit: 128 MB 

    Description

    Now we have a long long string, and we will have two kinds of operation on it.
    C i y: change the ith letter to y;
    Q i j: check whether the substring from ith letter to jth letter is a palindrome.
     
     

    Input

    There are multiple test cases.
    The first line contains a string whose length is not large than 1,000,000.
    The next line contains a integer N indicating the number of operations.
    The next N lines each lines contains a operation.
    All letters in the input are lower-case.

    Output

    For each query operation, output "yes" if the corresponding substring is a palindrome, otherwise output "no".

    Sample Input

    aaaaa 4 Q 1 5 C 2 b Q 1 5 Q 1 3

    Sample Output

    yes no yes

    HINT

    Source

    Adapted from a problem by yy17yy, 3x......
     
    题目大意: 输入一个10^6长字符串,然后M种操作,Q(i,j)为查询(i,j)的字串是否为回文串,C(i,ch)为将i位置字符改为ch。
     
    解题思路:若字符串为回文串,则其正序的hash值与其逆序的hash值相同。在这里我们使用多项式差值取模来求子串hash值,因为字符可限定为[1,26],所以基数设定为27。
     
    假设字符串为(a1,a2,a3,a4,..,an)  其hash编码为 a1*pow(27,0)+a2*pow(27,1)+..+an*pow(27,n-1) , 例如2进制表示一个序列,若不相等必定不会出现重复hash值。一样的原理。理论上如此,但是这里pow(27,10^6) 数值太大,必定溢出,为何不会出错我估计是数据不够大吧~~~
     
    通过hash值来简化字符串回文判定问题。使用树状数组来处理修改和数组和相加问题。时间复杂度O(m*log(n))
     
    View Code
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<math.h>
     5 #include<iostream>
     6 using namespace std;
     7 
     8 typedef unsigned long long LL;
     9 const int N = 1000007;
    10 
    11 LL bit[N], C[2][N];
    12 int n, m;
    13 char str[N];
    14 void update( int x, LL val, int flag )
    15 {
    16     for( ; x <= n; x += x&(-x) )
    17         C[flag][x] += val;
    18 }
    19 LL sum( int x, int flag )
    20 {
    21     LL res = 0;
    22     for( ; x >= 1; x -= x&(-x) )
    23         res += C[flag][x];
    24     return res;
    25 }
    26 void InitBit(){
    27     bit[0] = 1;
    28     for(int i = 1; i < N; i++)
    29         bit[i] = bit[i-1]*27;
    30 }
    31 void init(){
    32     n = strlen( str );
    33     memset( C, 0, sizeof(C) );
    34     for(int i = 1; i <= n; i++)
    35     {
    36         int j = (n+1)-i;    
    37         update( i, (str[i-1]-'a'+1)*bit[i-1], 0 );
    38         update( j, (str[i-1]-'a'+1)*bit[j-1], 1 ); 
    39     }
    40 }
    41  
    42 void solve(){
    43     scanf("%d", &m);
    44     char op[2], ch[2]; 
    45     int a, b, c, d;
    46     while( m-- )
    47     {
    48         scanf("%s", op);
    49         if( op[0] == 'Q' )
    50         {
    51             scanf("%d%d",&a,&b);
    52             if(a > b) swap(a,b);    
    53             d = (n+1)-a; c = (n+1)-b;
    54             LL hash0 = ( sum(b,0)-sum(a-1,0) )*bit[c-1];//对阶    
    55             LL hash1 = ( sum(d,1)-sum(c-1,1) )*bit[a-1];    
    56             puts( hash0 == hash1 ? "yes" : "no" );    
    57         }
    58         else
    59         {
    60             scanf("%d%s",&a,ch);
    61             b = (n+1)-a;
    62             update( a, (ch[0]-str[a-1])*bit[a-1], 0 );
    63             update( b, (ch[0]-str[a-1])*bit[b-1], 1 );
    64             str[a-1] = ch[0];    
    65         }
    66     }
    67 }
    68 int main(){
    69     InitBit();    
    70     while( scanf("%s",str) != EOF)
    71     {
    72         init();
    73         solve();
    74     }
    75     return 0;
    76 }
     
     
  • 相关阅读:
    Scrum是脆弱的,不敏捷的
    Solr 全文搜索
    Java并发之线程封闭
    Java中的关键字synchronized
    Java并发框架:Executor
    锁,表锁,行锁,页锁,共享锁,排他锁
    事务及事务隔离
    MySql存储引擎:innodb myisan memory
    树,二叉树
    B树(B-树) 、B+树
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2809078.html
Copyright © 2020-2023  润新知