zoukankan      html  css  js  c++  java
  • LCPhash求解

    今天学习了一种用hash求解lcp问题的方法。

    把一段内的hash表示为某个数x的递增次方乘上字符串相应位置的字母对应值,然后二分长度,判断两段的hash值是否相等就可以了。

    hash值可以用unsigned long long保存,这种类型能在溢出的时候自动mod2^64(看到书上说的)。

    cogs1849 jsoi火星人prefix

    题目大意:对于一个字符串,有修改、插入和查询x、y位置开始的最长公共字串的长度三种操作。

    思路:使用这种方法,在fhqTREEP上实现的。(但是常数比较大,所以bzoj上t掉了。。。)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #define xx 10007
    #define sigmasiz 26
    #define maxnode 100005
    using namespace std;
    unsigned long long mi[maxnode]={0};
    struct Node{
        Node* ch[2];
        char cc;
        int siz,r;
        unsigned long long hash;
        Node(char cc):cc(cc){ch[0]=ch[1]=NULL;r=rand();siz=1;hash=(cc-'a')+1;}
        void updata()
        {
            siz=1;hash=0;
            if (ch[0]!=NULL)
            {
                siz+=ch[0]->siz;
                hash+=ch[0]->hash;
            }
            hash+=mi[siz-1]*(cc-'a'+1);
            if (ch[1]!=NULL)
            {
                hash+=ch[1]->hash * mi[siz];
                siz+=ch[1]->siz;
            }
        }
    }*root;
    char ss[maxnode];
    int n;
    Node* merge(Node *aa,Node *bb)
    {
        if (aa==NULL) return bb;
        if (bb==NULL) return aa;
        if (aa->r < bb->r)
        {
            aa->ch[1]=merge(aa->ch[1],bb);
            if (aa!=NULL) aa->updata(); return aa;
        }
        else
        {
            bb->ch[0]=merge(aa,bb->ch[0]);
            if (bb!=NULL) bb->updata(); return bb;
        }
    }
    void split(Node *o,Node* &aa,Node* &bb,int x)
    {
        if (o==NULL){aa=bb=NULL;return;}
        if (x==0){aa=NULL;bb=o;return;}
        if (x==o->siz){aa=o;bb=NULL;return;}
        if ((o->ch[0]==NULL ? 0 : o->ch[0]->siz)>=x)
        {
            split(o->ch[0],aa,bb,x);
            o->ch[0]=bb;o->updata();bb=o;
        }
        else
        {
            split(o->ch[1],aa,bb,x-(o->ch[0]==NULL? 0 : o->ch[0]->siz)-1);
            o->ch[1]=aa;o->updata();aa=o;
        }
    }
    void change(Node* &o,int x,char c)
    {
        Node *a,*b,*y,*z;
        split(o,a,b,x-1);split(b,y,z,1);
        y=new Node(c);b=merge(y,z);o=merge(a,b);
    }
    void ins(Node* &o,int x,char c)
    {
        Node *a,*b,*y,*z;
        split(o,a,b,x);y=new Node(c);
        z=merge(a,y);o=merge(z,b);++n;
    }
    unsigned long long calc(Node* o,int z,int ll)
    {
        Node *a,*b,*x,*y;
        unsigned long long sum;
        split(o,a,b,z-1);split(b,x,y,ll);
        if (x!=NULL) sum=x->hash;
        else sum=0;
        b=merge(x,y);o=merge(a,b);
        return sum;
    }
    int ask(Node* o,int x,int y)
    {
        Node *a,*b,*p,*q;
        int l,r,mid,ss;
        l=0;r=ss=min(n-x+1,n-y+1);
        while(l<r)
        {
            mid=(l+r)/2;
            if (calc(o,x,ss-mid)==calc(o,y,ss-mid)) r=mid;
            else l=mid+1;
        }
        return ss-l;
    }
    int main()
    {
        int i,j,m,ll,a,b;
        char kk,c;
        mi[0]=1;root=NULL;
        for (i=1;i<maxnode;++i) mi[i]=mi[i-1]*xx;
        scanf("%s",&ss);n=strlen(ss);
        for (i=0;i<n;++i) 
        {
            Node *o;
            o=new Node(ss[i]);
            root=merge(root,o);
        }
        scanf("%d",&m);
        for (i=1;i<=m;++i)
        {
            while(kk=getchar())
                if (kk>='A'&&kk<='Z') break;
            if (kk=='Q') 
            {
                scanf("%d%d",&a,&b);
                printf("%d
    ",ask(root,a,b));
            }
            if (kk=='R')
            {
                scanf("%d",&a);
                while(c=getchar())
                  if (c>='a'&&c<='z') break;
                change(root,a,c);
            }
            if (kk=='I')
            {
                scanf("%d",&a);
                while(c=getchar())
                  if (c>='a'&&c<='z') break;
                ins(root,a,c);
            }
        }
    }
    View Code

     (把unsigned long long改为unsigned int,再加上inline,就从bzoj上a掉了。。。)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #define xx 10007
    #define sigmasiz 26
    #define maxnode 100005
    using namespace std;
    unsigned int mi[maxnode]={0};
    struct Node{
        Node* ch[2];
        char cc;
        int siz,r;
        unsigned int hash;
        Node(char cc):cc(cc){ch[0]=ch[1]=NULL;r=rand();siz=1;hash=(cc-'a')+1;}
        void updata()
        {
            siz=1;hash=0;
            if (ch[0]!=NULL)
            {
                siz+=ch[0]->siz;
                hash+=ch[0]->hash;
            }
            hash+=mi[siz-1]*(cc-'a'+1);
            if (ch[1]!=NULL)
            {
                hash+=ch[1]->hash * mi[siz];
                siz+=ch[1]->siz;
            }
        }
    }*root;
    char ss[maxnode];
    int n;
    inline Node* merge(Node *aa,Node *bb)
    {
        if (aa==NULL) return bb;
        if (bb==NULL) return aa;
        if (aa->r < bb->r)
        {
            aa->ch[1]=merge(aa->ch[1],bb);
            if (aa!=NULL) aa->updata(); return aa;
        }
        else
        {
            bb->ch[0]=merge(aa,bb->ch[0]);
            if (bb!=NULL) bb->updata(); return bb;
        }
    }
    inline void split(Node *o,Node* &aa,Node* &bb,int x)
    {
        if (o==NULL){aa=bb=NULL;return;}
        if (x==0){aa=NULL;bb=o;return;}
        if (x==o->siz){aa=o;bb=NULL;return;}
        if ((o->ch[0]==NULL ? 0 : o->ch[0]->siz)>=x)
        {
            split(o->ch[0],aa,bb,x);
            o->ch[0]=bb;o->updata();bb=o;
        }
        else
        {
            split(o->ch[1],aa,bb,x-(o->ch[0]==NULL? 0 : o->ch[0]->siz)-1);
            o->ch[1]=aa;o->updata();aa=o;
        }
    }
    inline void change(Node* &o,int x,char c)
    {
        Node *a,*b,*y,*z;
        split(o,a,b,x-1);split(b,y,z,1);
        y=new Node(c);b=merge(y,z);o=merge(a,b);
    }
    inline void ins(Node* &o,int x,char c)
    {
        Node *a,*b,*y,*z;
        split(o,a,b,x);y=new Node(c);
        z=merge(a,y);o=merge(z,b);++n;
    }
    inline unsigned int calc(Node* o,int z,int ll)
    {
        Node *a,*b,*x,*y;
        unsigned int sum;
        split(o,a,b,z-1);split(b,x,y,ll);
        if (x!=NULL) sum=x->hash;
        else sum=0;
        b=merge(x,y);o=merge(a,b);
        return sum;
    }
    inline int ask(Node* o,int x,int y)
    {
        Node *a,*b,*p,*q;
        int l,r,mid,ss;
        l=0;r=ss=min(n-x+1,n-y+1);
        while(l<r)
        {
            mid=(l+r)/2;
            if (calc(o,x,ss-mid)==calc(o,y,ss-mid)) r=mid;
            else l=mid+1;
        }
        return ss-l;
    }
    int main()
    {
        int i,j,m,ll,a,b;
        char kk,c;
        mi[0]=1;root=NULL;
        for (i=1;i<maxnode;++i) mi[i]=mi[i-1]*xx;
        scanf("%s",&ss);n=strlen(ss);
        for (i=0;i<n;++i) 
        {
            Node *o;
            o=new Node(ss[i]);
            root=merge(root,o);
        }
        scanf("%d",&m);
        for (i=1;i<=m;++i)
        {
            while(kk=getchar())
                if (kk>='A'&&kk<='Z') break;
            if (kk=='Q') 
            {
                scanf("%d%d",&a,&b);
                printf("%d
    ",ask(root,a,b));
            }
            if (kk=='R')
            {
                scanf("%d",&a);
                while(c=getchar())
                  if (c>='a'&&c<='z') break;
                change(root,a,c);
            }
            if (kk=='I')
            {
                scanf("%d",&a);
                while(c=getchar())
                  if (c>='a'&&c<='z') break;
                ins(root,a,c);
            }
        }
    }
    View Code
  • 相关阅读:
    08.net网站开发(前端):5.jQuery
    weblogic的ejb远程调用
    UVa 10131: Is Bigger Smarter?
    Qt5 FOR WINCE7, Visual Studio 2008环境的搭建
    Web常见安全漏洞原理及防范-学习笔记
    【转载】Spark学习 & 机器学习
    公司hadoop客户端试用
    Zen of Python(Python的19条哲学)
    【转载】GitHub中国区前100名到底是什么样的人
    【转载】Spark学习——入门
  • 原文地址:https://www.cnblogs.com/Rivendell/p/4621112.html
Copyright © 2011-2022 走看看