zoukankan      html  css  js  c++  java
  • BZOJ[2780][Spoj]8093 Sevenk Love Oimaster 后缀数组

    此题精神AC
    这里写图片描述

    SAM水题,但是我不会SAM
    将所有串串在一起,对这个大串求SA
    对于每一个模式串,能匹配的都是在rk意义上连续的一段
    二分出这一段的左右端点
    现在要做的就是统计这段区间有多少不同的颜色
    然后就同呵呵的项链
    我就是要用莫队来做(UPD 发blog10min以后:BIT也过不了)
    本机300ms,校OJ 700msA了
    能用的卡常技巧我都用了
    这篇博客留着等以后卡常的时候参考

    代码如下:
    莫队

    #include<algorithm>
    #include<ctype.h>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #pragma GCC optimize(3)
    #pragma GCC optimize(2)
    #define N 600050
    using namespace std;
    inline char nc(){
        static char buf[1000000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read(){
        register int x=0,f=1;char c;
        do c=nc(),f=c=='-'?-1:f; while(!isdigit(c));
        do x=(x<<3)+(x<<1)+c-'0',c=nc(); while(isdigit(c));
        return x*f;
    }
    int n,m,top,t,tot,len,l,r,mid,Block_Size,tmp,top1;
    typedef int iarr[N];
    iarr a,SA,rk,buck,las,height,ans,L,R,pw,block,num,s1;
    int f[N][25];
    char s[N];
    inline int Max(int a,int b){return a>b?a:b;}
    inline int Min(int a,int b){return a<b?a:b;}
    inline bool judge(int x,int y,int k){
        return las[x]==las[y] && las[x+k]==las[y+k];
    }
    inline void Radix_Sort(){
        for(register int i=1;i<=m;++i) buck[i]=0;
        for(register int i=1;i<=n;++i) buck[rk[las[i]]]++;
        for(register int i=2;i<=m;++i) buck[i]+=buck[i-1];
        for(register int i=n;i>=1;--i) SA[buck[rk[las[i]]]--]=las[i];
        top=m=0;
    }
    inline void Get_SA(){
        for(register int i=1;i<=n;++i){
            rk[i]=s[i];las[i]=i;
        }
        m=127;Radix_Sort();
        for(register int i=1;m^n;i<<=1){
            for(register int j=n-i+1;j<=n;++j) las[++top]=j;
            for(register int j=1;j<=n;++j) if(SA[j]>i) las[++top]=SA[j]-i;
            Radix_Sort();
            for(register int j=1;j<=n;++j) las[j]=rk[j];
            for(register int j=1;j<=n;++j) rk[SA[j]]=judge(SA[j-1],SA[j],i)?m:++m;
        }
        for(register int i=1,j=0;i<=n;++i,j=j?j-1:0){
            while(s[i+j]==s[SA[rk[i]-1]+j]) ++j;
            height[rk[i]]=j;
        }
    }
    inline void Get_ST(){
        pw[0]=1;
        for(register int i=1;pw[i-1]<=n;++i) pw[i]=1<<i;
        for(register int i=1;i<=n;++i) f[i][0]=height[i];
        for(register int j=1;pw[j]<=n;++j)
            for(register int i=1;i+pw[j-1]<=n;++i)
                f[i][j]=Min(f[i+pw[j-1]][j-1],f[i][j-1]);
    }
    inline int LCP(int x,int y){
        if(x>y) swap(x,y);
        int t=log2(y-x+1);
        return Min(f[x][t],f[y-pw[t]+1][t]);
    }
    struct Query{
        int l,r,id;
    }q[N];
    inline bool cmp(Query a,Query b){
        return block[a.l]==block[b.l]?a.r<b.r:block[a.l]<block[b.l];
    }
    inline void Update(int x,int k){
        if(!~x) return;
        if(!num[x]) ++tmp;
        num[x]+=k;
        if(!num[x]) --tmp;
    }
    int main(){
        memset(a,-1,sizeof a);
        n=read();tot=read();
        for(register int i=1;i<=n;i++){
            do s[++top]=nc(),a[top]=i; while(isalpha(s[top]));
            s[top]=126;
        }
        for(register int i=1;i<=tot;i++){
            L[i]=top+1;
            do s[++top]=nc(); while(isalpha(s[top]));
            R[i]=top-1;
            s[top]=126;
        }
        n=top;
        Get_SA();Get_ST();
        Block_Size=sqrt(tot);
        for(register int i=1;i<=tot;i++){
            block[i]=(i-1)/Block_Size+1;
            len=R[i]-L[i]+1;
            L[i]=rk[L[i]];
            l=1;r=L[i]-1;
            if(height[L[i]]<len) q[i].l=L[i];
            else while(l<=r){
                mid=l+r>>1;
                if(LCP(mid+1,L[i])>=len)
                    q[i].l=mid,r=mid-1;
                else l=mid+1;
            }
            l=L[i]+1;r=n;
            if(height[L[i]+1]<len) q[i].r=L[i];
            else while(l<=r){
                mid=l+r>>1;
                if(LCP(L[i]+1,mid)>=len)
                    q[i].r=mid,l=mid+1;
                else r=mid-1;
            }
            q[i].id=i;
        }
        sort(q+1,q+tot+1,cmp);
        l=1;r=0;
        for(register int i=1;i<=tot;i++){
            while(l<q[i].l) Update(a[SA[l++]],-1);
            while(l>q[i].l) Update(a[SA[--l]],1);
            while(r<q[i].r) Update(a[SA[++r]],1);
            while(r>q[i].r) Update(a[SA[r--]],-1);
            ans[q[i].id]=tmp;
        }
        for(register int i=1;i<=tot;i++){
            printf("%d\n",ans[i]);
        }
        return 0;
    }
    

    BIT

    #include<algorithm>
    #include<cstdio>
    #pragma GCC optimize(3)
    #define isdigit(c) (c>='0' && c<='9')
    #define isalpha(c) (c>='a' && c<='z')
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++)
    #define judge(a,b,c) (las[a]==las[b] && las[a+c]==las[b+c])
    #define Swap(a,b) (a=a^b,b=a^b,a=a^b)
    #define Min(a,b) (a<b?a:b)
    #define Add(a,b) for(;a<=n;a=a+(a&-a)) g[a]+=b;
    #define Update(x,k) if(x){\
        if(!num[x]) ++tmp;\
        num[x]=num[x]+k;\
        if(!num[x]) --tmp;}
    #define N 600050
    using namespace std;
    char buf[N],*p1=buf,*p2=buf;
    int xx,ff;
    char c;
    inline int read(){
        xx=0;ff=1;
        do c=nc(),ff=c=='-'?-1:ff; while(!isdigit(c));
        do xx=(xx<<3)+(xx<<1)+c-'0',c=nc(); while(isdigit(c));
        return xx*ff;
    }
    int n,m,top,t,len,tmp,top1;
    int a[N],SA[N],rk[N],buck[N],las[N],height[N],ans[N],L[N],R[N],pw[N],num[N],g[N],nex[N],b[N],log2[N],s1[31];
    int f[25][N];
    char s[N];
    inline void Radix_Sort(){
        register int i;
        for(i=1;i<=m;++i) buck[i]=0;
        for(i=1;i<=n;++i) buck[rk[las[i]]]++;
        for(i=2;i<=m;++i) buck[i]+=buck[i-1];
        for(i=n;i>=1;--i) SA[buck[rk[las[i]]]--]=las[i];
        top=m=0;
    }
    inline void Get_SA(){
        register int i,j;
        for(i=1;i<=n;++i){
            rk[i]=s[i];las[i]=i;
        }
        m=127;Radix_Sort();
        for(i=1;m^n;i<<=1){
            for(j=n-i+1;j<=n;++j) las[++top]=j;
            for(j=1;j<=n;++j) if(SA[j]>i) las[++top]=SA[j]-i;
            Radix_Sort();
            for(j=1;j<=n;++j) las[j]=rk[j];
            for(j=1;j<=n;++j) rk[SA[j]]=judge(SA[j-1],SA[j],i)?m:++m;
        }
        for(i=1,j=0;i<=n;++i,j=j?j-1:0){
            while(s[i+j]==s[SA[rk[i]-1]+j]) ++j;
            height[rk[i]]=j;
        }
    }
    inline void Get_ST(){
        pw[0]=1;
        register int i,j;
        for(i=1;pw[i-1]<=n;++i){
            pw[i]=1<<i;
            for(j=pw[i-1]+1;j<=pw[i];j++) log2[j]=i-1;
        }
        for(i=1;i<=n;++i) f[0][i]=height[i];
        for(j=1;pw[j]<=n;++j)
            for(i=1;i+pw[j-1]<=n;++i)
                f[j][i]=Min(f[j-1][i+pw[j-1]],f[j-1][i]);
    }
    inline int LCP(register int x,register int y){
        if(x>y) Swap(x,y);
        register int t=log2[y-x+1];
        return Min(f[t][x],f[t][y-pw[t]+1]);
    }
    struct Query{
        int l,r,id;
    }q[N];
    inline char cmp(register Query a,register Query b){
        return a.l<b.l;
    }
    inline int Sum(register int x){
        register int tmp=0;
        for(;x;x=x-(x&-x))
            tmp=tmp+g[x];
        return tmp;
    }
    inline void write(int x){
        top1=0;
        while(x){
            s1[++top1]=x%10;
            x=x/10;
        }
        for(register int i=top1;i;i--) putchar(s1[i]+'0');putchar('\n');
    }
    main(){
        freopen("aa1.in","r",stdin);
        freopen("u.out","w",stdout);
        register int i,j,l,r,mid,maxx,tot;
        maxx=n=read();tot=read();
        for(i=1;i<=n;i+=2){
            do s[++top]=nc(),a[top]=i; while(isalpha(s[top]));
            s[top]=126;
            if(i+1>n) break;
            do s[++top]=nc(),a[top]=i+1; while(isalpha(s[top]));
            s[top]=126;
        }
        for(i=1;i<=tot;i+=2){
            L[i]=top+1;
            do s[++top]=nc(); while(isalpha(s[top]));
            R[i]=top-1;
            s[top]=126;
            if(i+1>tot) break;
            L[i+1]=top+1;
            do s[++top]=nc(); while(isalpha(s[top]));
            R[i+1]=top-1;
            s[top]=126;
        }
        n=top;
        Get_SA();Get_ST();
        for(i=1;i<=tot;++i){
            len=R[i]-L[i]+1;
            L[i]=rk[L[i]];
            l=1;r=L[i]-1;
            if(height[L[i]]<len) q[i].l=L[i];
            else while(l<=r){
                mid=l+r>>1;
                if(LCP(mid+1,L[i])>=len)
                    q[i].l=mid,r=mid-1;
                else l=mid+1;
            }
            l=L[i]+1;r=n;
            if(height[L[i]+1]<len) q[i].r=L[i];
            else while(l<=r){
                mid=l+r>>1;
                if(LCP(L[i]+1,mid)>=len)
                    q[i].r=mid,l=mid+1;
                else r=mid-1;
            }
            q[i].id=i;
        }
        sort(q+1,q+tot+1,cmp);
        for(i=n;i>=1;i-=2){
            if(a[SA[i]]) nex[i]=b[a[SA[i]]],b[a[SA[i]]]=i;
            if(i-1>=1 && a[SA[i-1]]) nex[i-1]=b[a[SA[i-1]]],b[a[SA[i-1]]]=i-1;
        }
        for(i=1;i<=maxx;i+=2){
            if(b[i]) Add(b[i],1);
            if(i+1<=maxx && b[i+1]) Add(b[i+1],1);
        }
        l=1;
        for(i=1;i<=tot;i+=2){
            while(l<q[i].l){
                if(nex[l]) Add(nex[l],1);
                ++l;
            }
            ans[q[i].id]=Sum(q[i].r)-Sum(q[i].l-1);
            if(i+1>tot){
                break;
            }
            while(l<q[i+1].l){
                if(nex[l]) Add(nex[l],1);
                ++l;
            }
            ans[q[i+1].id]=Sum(q[i+1].r)-Sum(q[i+1].l-1);
        }
        for(i=1;i<=tot;i+=2){
            write(ans[i]);
            if(i+1<=tot) write(ans[i+1]);
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    07 JavaWeb
    06 XML编程(CRUD)
    05 XML
    04 DOM一窥
    03 Javascript初识
    02 CSS/javaScript
    01 HTML基础
    09_IO流
    08_集合概述
    07_基本数据类型和包装类
  • 原文地址:https://www.cnblogs.com/Duan2baka/p/8659601.html
Copyright © 2011-2022 走看看