zoukankan      html  css  js  c++  java
  • uva12338(后缀树组)

    Anti-Rhyme Pairs

    题意:

      给出n个字符串,q个询问,每次询问为i,j两个数字,求第i个字符串和第j个字符串的最长公共前缀。

    分析:

      将n个字符串拼接后,第i个字符串与第j个字符串的最长公共前缀也可看作第i个字符串首字母在拼接字符串中的位置的后缀与第j个字符串首字母在拼接字符串中的位置的后缀的最长公共前缀,即height数组的含义。根据后缀树组中height数组的性质,suffix(i)和suffix(j)的最长公共前缀为height【rank【i】+1】,height【rank【i】+2】……height【rank【j】】中的最小值(代码中因为数据存储在数组中的位置不同,导致下标有所变化),用ST表维护一个区间最小值即可。

    代码:

    #include <map>
    #include <queue>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxlog=20;
    const int maxn=2e6;
    
    int n,q,T;
    
    char str[maxn];
    int arrlen[maxn],sum[maxn];
    int r[maxn],sa[maxn],Rank[maxn],height[maxn];
    
    namespace Suffix {
        int wa[maxn],wb[maxn],wv[maxn],wt[maxn];
        int cmp(int *r,int a,int b,int k)
        {
            return r[a]==r[b]&&r[a+k]==r[b+k];
        }
        void da(int *r,int *sa,int n,int m)
        {
            int i,j,p,*x=wa,*y=wb,*t;
            for(i=0; i<m; i++)  wt[i]=0;
            for(i=0; i<=n; i++)  wt[x[i]=r[i]]++;
            for(i=1; i<m; i++)  wt[i]+=wt[i-1];
            for(i=n; i>=0; i--)  sa[--wt[x[i]]]=i;
            p=1;
            j=1;
            for(; p<=n; j*=2,m=p)
            {
                for(p=0,i=n+1-j; i<=n; i++)  y[p++]=i;
                for(i=0; i<=n; i++)  if(sa[i]>=j)  y[p++]=sa[i]-j;
                for(i=0; i<=n; i++)  wv[i]=x[y[i]];
                for(i=0; i<m; i++)  wt[i]=0;
                for(i=0; i<=n; i++)  wt[wv[i]]++;
                for(i=1; i<m; i++)  wt[i]+=wt[i-1];
                for(i=n; i>=0; i--)  sa[--wt[wv[i]]]=y[i];
                t=x;
                x=y;
                y=t;
                x[sa[0]]=0;
                for(p=1,i=1; i<=n; i++)
                    x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
            }
        }
        void getheight(int *r,int* sa,int n)
        {
            int i,j,k=0;
            for(i=1; i<=n; i++)  Rank[sa[i]]=i;
            for(i=0; i<n; i++)
            {
                if(k)
                    k--;
                else
                    k=0;
                j=sa[Rank[i]-1];
                while(r[i+k]==r[j+k])
                    k++;
                height[Rank[i]-1]=k;
            }
        }
    };
    
    namespace ST {
        int d[maxn][maxlog];
        void init(int* a,int n)
        {
            for(int i=1;i<=n;i++)    d[i][0]=height[i];
            for(int j=1;(1<<j)<=n;j++){
                for(int i=1;i+(1<<j)<=n;i++){
                    d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
                }
            }
        }
        int query(int L,int R)
        {
            int k=0;
            while((1<<(k+1))<=R-L+1)    k++;
            return min(d[L][k],d[R-(1<<k)+1][k]);
        }
    };
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        scanf("%d",&T);
        for(int kase=1;kase<=T;kase++){
            int tot=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%s",str);
                int slen=strlen(str);
                arrlen[i]=slen;
                if(i==1)    sum[i]=0;
                else        sum[i]=sum[i-1]+arrlen[i-1]+1;
    
                for(int j=0;j<slen;j++){
                    r[tot++]=str[j]-'a'+1;
                }
                r[tot++]=29+i;
            }
            r[tot]=0;
    
            Suffix::da(r,sa,tot,30+n);
            Suffix::getheight(r,sa,tot);
            ST::init(height,tot);
    
            scanf("%d",&q);
            printf("Case %d:
    ",kase);
            for(int i=1;i<=q;i++){
                int L,R;
                scanf("%d %d",&L,&R);
                if(L==R){
                    printf("%d
    ",arrlen[L]);
                    continue;
                }
                L=Rank[sum[L]],R=Rank[sum[R]];
                if(L>R) swap(L,R);
                printf("%d
    ",ST::query(L,R-1));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Aurora 数据库支持多达五个跨区域只读副本
    Amazon RDS 的 Oracle 只读副本
    Amazon EC2 密钥对
    DynamoDB 读取请求单位和写入请求单位
    使用 EBS 优化的实例或 10 Gb 网络实例
    启动 LAMP 堆栈 Web 应用程序
    AWS 中的错误重试和指数退避 Error Retries and Exponential Backoff in AWS
    使用 Amazon S3 阻止公有访问
    路由表 Router Table
    使用MySQLAdmin工具查看QPS
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9458826.html
Copyright © 2011-2022 走看看