• BZOJ3230: 相似子串


    (权限题。。

    做出正反后缀数组。。二分找出询问子串所在的后缀。。再加上rmq。。。

    (说起来很简单但是细节还是很多的。。

    比如说怎么二分找出询问子串所在的后缀呢。可以先找出每个后缀在所有子串中的排名,设这个排名为sub[i],有sub[i]=sub[i-1]+n-sa[i]+1-height[i](n-sa[i]+1就可以获得这个后缀的长度,然后再减掉与上一个后缀的重复部分)

    答案的最小值要算上这两个子串的长度。子串的长度怎么算呢。比如说这个子串排名为k,所在的后缀为i,len=height[i]+k-sub[i-1](重复的部分加上比上一个串多的部分)

    那它在逆串的位置?rev=n-(sa[i]+len-1)+1(就是找出这个子串最后一个字符所在的位置,然后逆过来)

    (上面的其实都非常显然啦。。。你萌就别吐槽蒟蒻的智商了TAT。。。

    (代码很丑很慢。。。因为蒟蒻并不会基数排序TAT。。。

    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define maxn 200500
    #define inf int(1e9)
    #define ll long long
    #define mm 1000000007
    #define eps 1e-9
    #define low(x) x&(-x)
    using namespace std;
    char ch[maxn];
    int s[maxn];
    ll sub[maxn];
    int n,q;
    ll read(){
        ll x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    struct SA{
        struct node{int x,y,sa;
            bool operator <(const node &o) const{
                return x<o.x||(x==o.x&&y<o.y);
            }
        }a[maxn];
        int rank[maxn],sa[maxn],h[maxn],height[maxn];
        ll f[maxn][21];
        void build(){
            rep(i,1,n) rank[i]=s[i];
            int p=1;
            while (p<=n){
                rep(i,1,n) a[i].x=rank[i],a[i].y=rank[i+p],a[i].sa=i;
                sort(a+1,a+1+n);
                int sum=1; rank[a[1].sa]=1;
                rep(i,2,n) {
                    if (a[i].x!=a[i-1].x||a[i].y!=a[i-1].y) sum++;
                    rank[a[i].sa]=sum;
                }
                if (sum==n) break;
                p*=2;
            }
            rep(i,1,n) sa[i]=a[i].sa;
            int j=1,k=0;
            rep(i,1,n){
                if (sa[1]==i) {h[i]=0; j=0;}
                else {
                    if (j) j--;
                    h[i]=j; k=0;
                    while (i+j+k<=n&&sa[rank[i]-1]+j+k<=n){
                        if (s[i+j+k]==s[sa[rank[i]-1]+j+k]) h[i]++; else break;
                        k++;
                    } 
                    j=h[i];
                }
            }
            rep(i,1,n) height[i]=h[sa[i]];
        }
        void init(){
            int b=int(log2(n))+1;
            rep(i,1,n) f[i][0]=height[i];
            rep(i,1,b) rep(j,1,n) f[j][i]=min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
        }
        ll rmq(int l,int r){
            if (l>r) return inf;
            int k=0;
            while (1<<(k+1)<=r-l+1) k++;
            return min(f[l][k],f[r-(1<<k)+1][k]);
        }
    }A,B;
    void get(ll val,int &i,ll &len,ll &rev){
        i=lower_bound(sub+1,sub+1+n,val)-sub;
        len=A.height[i]+val-sub[i-1];
        rev=n-(A.sa[i]+len-1)+1;
    }
    int main(){
        n=read(); q=read();
        scanf("%s",ch+1);
        if (!n) {while (q--) puts("-1"); return 0;}
        rep(i,1,n) s[i]=ch[i]-'a'+1; A.build(); A.init();
        rep(i,1,n) s[i]=ch[n-i+1]-'a'+1; B.build(); B.init();
        rep(i,1,n) sub[i]=sub[i-1]+n-A.sa[i]+1-A.height[i];
        ll rev0,rev1,a,b,len0,len1,l,r;
        int i,j;
        while (q--){
            ll x=read(),y=read();
            if (x>y) swap(x,y);
            if (x>sub[n]||y>sub[n]) {puts("-1"); continue;}
            get(x,i,len0,rev0); get(y,j,len1,rev1);
            a=min(min(len0,len1),A.rmq(i+1,j));
            l=min(B.rank[rev0],B.rank[rev1]); r=max(B.rank[rev0],B.rank[rev1]);
            b=min(min(len0,len1),B.rmq(l+1,r));
            printf("%lld
    ",1LL*a*a+1LL*b*b);
        }    
        return 0;
    }
  • 相关阅读:
    如何完全备份android在系统system分区和data分
    U3D游戏开发商思考
    安德鲁斯Toast它们的定义和防止重复显示器
    android反射组件 (一个)java 它们的定义annotation基础知识
    ZOJ 3794 Greedy Driver spfa
    [LeetCode OJ] Copy List with Random Pointer 扩大
    LAN公布java web项目的方法的外侧
    [RxJS] Creation operator: create()
    [RxJS] Creation operators: interval and timer
    [Unit Testing] Angular Test component with required
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5181691.html
Copyright © 2020-2023  润新知