ACdreamoj 1011(树状数组维护字符串hash前缀和)

来源:互联网 发布:淘宝图片放大镜js代码 编辑:程序博客网 时间:2024/06/12 00:58

题目链接:http://acdream.info/problem?pid=1019

题意:两种操作,第一种将字符串某个位置的字符换为另一个字符;第二种查询某个连续子序列是否是回文串;

解法:有两种hash的办法,所以写了两种解法;首先hash是x1 * p^1+ x2*p^2 +x3*p^3...可以用树状数组维护前缀和,维护两个串,一个是正串,另一个是反串用于比较。比较时候乘以相应的p倍数判断是否相等;
刘汝佳白书上的hash方法处理这道题更复杂:修改i会对后缀j产生的影响为a*p^(i-j),那么把这个式子变成a * p^i *p^(-j)  然后就是在这个位置加上a * p^i,以后查询每个i
位置的hash值后都乘以p^i.


第一分代码:

/******************************************************* @author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8#define zero(_) (abs(_)<=eps)const double pi=acos(-1.0);typedef unsigned long long LL;const int Max=1000010;const int INF=1e9+7;char s[Max];LL C[2][Max];LL Hash[Max];int seed=13;void init(){    Hash[0]=1;    for(int i=1; i<Max; i++)        Hash[i]=Hash[i-1]*seed;}int len;void update(int i,int pos,LL data){    while(pos<=len)    {        C[i][pos]+=data;        pos+=pos&(-pos);    }}LL get(int i,int pos){    LL ans=0;    while(pos)    {        ans+=C[i][pos];        pos-=pos&(-pos);    }    return ans;}LL gethash(int i,int l,int r){    return get(i,r)-get(i,l-1);}int main(){    init();    while(scanf("%s",s+1)==1)    {        memset(C,0,sizeof C);        int t;        cin>>t;        len=strlen(s+1);        for(int i=1; i<=len; i++)        {            update(0,i,(s[i]-'a')*Hash[i]);            update(1,len+1-i,(s[i]-'a')*Hash[len+1-i]);        }        while(t--)        {            char c;            getchar();            scanf("%c",&c);            if(c=='C')            {                char b[5];                int a;                scanf("%d%s",&a,b);                update(0,a,-(s[a]-'a')*Hash[a]);                update(0,a,(b[0]-'a')*Hash[a]);                update(1,len+1-a,-(s[a]-'a')*Hash[len+1-a]);                update(1,len+1-a,(b[0]-'a')*Hash[len+1-a]);                s[a]=b[0];            }            else            {                int l,r;                scanf("%d%d",&l,&r);                if(gethash(0,l,r)*Hash[len-l]==gethash(1,len+1-r,len+1-l)*Hash[r-1])                    puts("yes");                else                    puts("no");            }        }    }    return 0;}

第二份代码:

/******************************************************* @author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8#define zero(_) (abs(_)<=eps)const double pi=acos(-1.0);typedef  unsigned long long LL;const int Max=1000010;const LL INF=1000000007;char s[Max];char s2[Max];LL Hash[Max];LL C[Max];LL C2[Max];int seed=13;int len;void init(){    Hash[0]=1;    for(int i=1; i<Max; i++)        Hash[i]=(Hash[i-1]*seed)%INF;}LL pow1(LL a,LL k){    LL ans=1;    while(k)    {        if(k&1)            ans=(ans*a)%INF;        a=(a*a)%INF;        k>>=1;    }    return ans;}void update(int pos,LL value){    while(pos!=0)    {        C[pos]=(C[pos]+value+INF)%INF;        pos-=pos&(-pos);    }}void update2(int pos,LL value){    while(pos!=0)    {        C2[pos]=(C2[pos]+value+INF)%INF;        pos-=pos&(-pos);    }}LL query(int pos){    LL ans=0;    while(pos<=len+1)    {        ans=(ans+C[pos])%INF;        pos+=pos&(-pos);    }    return ans;}LL query2(int pos){    LL ans=0;    while(pos<=len+1)    {        ans=(ans+C2[pos])%INF;        pos+=pos&(-pos);    }    return ans;}LL get(int now){    LL ans=query(now);    return (pow1(pow1(seed,now),INF-2)%INF*ans)%INF;}LL gethash(int l,int r){    return (get(l)-get(r+1)*Hash[r+1-l]%INF+INF)%INF;}LL get2(int now){    LL ans=query2(now);    return (pow1(pow1(seed,now),INF-2)%INF*ans)%INF;}LL gethash2(int l,int r){    return (get2(l)-get2(r+1)*Hash[r+1-l]%INF+INF)%INF;}int main(){    init();    while(scanf("%s",s+1)==1)    {        int t;        scanf("%d",&t);        len=strlen(s+1);        strcpy(s2+1,s+1);        reverse(s2+1,s2+len+1);        memset(C,0,sizeof C);        memset(C2,0,sizeof C2);        for(int i=1; i<=len; i++)        {            update(i,(s[i]-'a')*Hash[i]%INF);//a*x^(i-j)=a*x^i*(x^-j);            update2(i,(s2[i]-'a')*Hash[len+1-i]%INF);        }        while(t--)        {            char c[5];            scanf("%s",c);            //printf(c);            if(c[0]=='C')            {                int a;                char b[5];                scanf("%d%s",&a,b);                update(a,('a'-s[a])*Hash[a]%INF);                update(a,(b[0]-'a')*Hash[a]%INF);                update2(len+1-a,('a'-s2[len+1-a])*Hash[len+1-a]%INF);                update2(len+1-a,(b[0]-'a')*Hash[len+1-a]%INF);                s[a]=b[0];                s2[len+1-a]=b[0];            }            else            {                int l;                int r;                scanf("%d%d",&l,&r);                if(r-l<=1)                {                    puts("yes");                    continue;                }                if(gethash(l,r)==gethash2(len+1-r,len+1-l))                    puts("yes");                else                    puts("no");            }        }    }    return 0;}


0 0
原创粉丝点击