acdream 1019: Palindrome 字符串多项式取Hash值
1019: Palindrome
Time Limit: 1 Sec Memory Limit: 128 MBDescription
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 }