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 }

 

 
 

你可能感兴趣的:(hash)