BZOJ-3230: 相似子串(后缀数组+RMQ+二分查找)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3230

首先对原串和原串反过来的串做后缀数组,求出sa[],rank[],height[],然后利用height[]查询最长公共前缀后缀,然后二分查找排名为i,j的子串位置,然后得出答案,记得long long。

代码:

09fa513d269759ee65948ccdb0fb43166c22dff4.jpg.png
#include 
#include 
#include 
#include 
 
using namespace std;
 
#define MAXN 200100
#define inf 0x7fffffff
#define MAXB 21
 
char s0[MAXN],s1[MAXN];
int sa0[MAXN],rank0[MAXN],height0[MAXN],sa1[MAXN],rank1[MAXN],height1[MAXN];
int n,m;
 
int w[MAXN],r[MAXN],x[MAXN],y[MAXN];
 
void make_sa(char *s,int N,int *sa,int *rank,int *height) {
    s[0]=sa[0]=0;
    int Nn,b=1,M=N;
    for (int i=0;i++r) return 0x7fffffff;
    int k=int(log2(r-l+1));
    return u==0?min(st0[l][k],st0[r-(1<suff[n-1]) return n;
    while (right-left>1) {
        int mid=(left+right)>>1;
        if (x>suff[mid]) left=mid
            ;  else right=mid;
    }
    return right;
}
 
long long MIN(long long a,long long b) {
    if (aj) swap(i,j);
        if (i>suff[n]||j>suff[n]) {
            printf("-1\n");
            continue;
        }
        int f0=Binary_Search(i),f1=Binary_Search(j);
        long long a,b,len0=height0[f0]+i-suff[f0-1],len1=height0[f1]+j-suff[f1-1];
        a=MIN(MIN(len0,len1),Min(f0+1,f1,0));
        long long c0=n-(sa0[f0]+len0-1)+1,c1=n-(sa0[f1]+len1-1)+1;
        int ll=min(rank1[c0],rank1[c1]),rr=max(rank1[c0],rank1[c1]);
        b=MIN(MIN(len0,len1),Min(ll+1,rr,1));
        long long ans=a*a+b*b;
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(BZOJ-3230: 相似子串(后缀数组+RMQ+二分查找))