zoukankan      html  css  js  c++  java
  • BZOJ3230 相似子串 【后缀数组】

    题目链接

    BZOJ3230
    权限题

    题解

    后缀数组基础题
    询问第K大不同子串和正反lcp长度
    如果您RE了,您就要知道询问的输入会爆LL

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    using namespace std;
    const int maxn = 400005,maxm = 100005,INF = 1000000000;
    inline LL read(){
    	LL out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int n,m,bac[maxn],t1[maxn],t2[maxn],bin[50],Log[maxn];
    LL sum[maxn];
    struct SA{
    	char s[maxn];
    	int sa[maxn],rank[maxn],height[maxn],mn[maxn][18];
    	void getsa(){
    		int *x = t1,*y = t2; m = 255;
    		for (int i = 0; i <= m; i++) bac[i] = 0;
    		for (int i = 1; i <= n; i++) bac[x[i] = s[i]]++;
    		for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
    		for (int i = n; i; i--) sa[bac[x[i]]--] = i;
    		for (int k = 1; k <= n; k <<= 1){
    			int p = 0;
    			for (int i = n - k + 1; i <= n; i++) y[++p] = i;
    			for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
    			for (int i = 0; i <= m; i++) bac[i] = 0;
    			for (int i = 1; i <= n; i++) bac[x[y[i]]]++;
    			for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
    			for (int i = n; i; i--) sa[bac[x[y[i]]]--] = y[i];
    			swap(x,y);
    			x[sa[1]] = p = 1;
    			for (int i = 2; i <= n; i++)
    				x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
    			if (p >= n) break;
    			m = p;
    		}
    		for (int i = 1; i <= n; i++) rank[sa[i]] = i;
    		for (int i = 1,k = 0; i <= n; i++){
    			if (k) k--;
    			int j = sa[rank[i] - 1];
    			while (s[i + k] == s[j + k]) k++;
    			height[rank[i]] = k;
    		}
    		for (int i = 1; i <= n; i++) mn[i][0] = height[i];
    		for (int j = 1; j <= 17; j++)
    			for (int i = 1; i <= n; i++){
    				if (i + bin[j] - 1 > n) break;
    				mn[i][j] = min(mn[i][j - 1],mn[i + bin[j - 1]][j - 1]);
    			}
    	}
    	int lcp(int x,int y){
    		if (x == y) return n - x + 1;
    		int l = rank[x],r = rank[y];
    		if (l > r) swap(l,r); l++;
    		int t = Log[r - l + 1];
    		return min(mn[l][t],mn[r - bin[t] + 1][t]);
    	}
    }L,R;
    void init(){
    	sum[1] = n - L.sa[1] + 1;
    	for (int i = 2; i <= n; i++)
    		sum[i] = sum[i - 1] + (n - L.sa[i] + 1) - L.height[i];
    }
    int q;
    void solve(){
    	LL f,a,b,x,y;
    	int l1,r1,l2,r2;
    	while (q--){
    		x = read(); y = read();
    		if (x > sum[n] || y > sum[n]) {puts("-1"); continue;}
    		int p = lower_bound(sum + 1,sum + 1 + n,x) - sum;
    		int q = lower_bound(sum + 1,sum + 1 + n,y) - sum;
    		if (sum[p] == x) l1 = L.sa[p],r1 = n;
    		else l1 = L.sa[p],r1 = n - (sum[p] - x);
    		if (sum[q] == y) l2 = L.sa[q],r2 = n;
    		else l2 = L.sa[q],r2 = n - (sum[q] - y);
    		a = min(L.lcp(l1,l2),min(r1 - l1 + 1,r2 - l2 + 1));
    		b = min(R.lcp(n - r1 + 1,n - r2 + 1),min(r1 - l1 + 1,r2 - l2 + 1));
    		f = a * a + b * b;
    		printf("%lld
    ",f);
    	}
    }
    int main(){
    	bin[0] = 1; for (int i = 1; i <= 30; i++) bin[i] = bin[i - 1] << 1;
    	Log[0] = -1; for (int i = 1; i <= 100000; i++) Log[i] = Log[i >> 1] + 1;
    	n = read(); q = read();
    	scanf("%s",L.s + 1);
    	for (int i = 1; i <= n; i++) R.s[i] = L.s[n - i + 1];
    	L.getsa(); R.getsa();
    	init(); solve();
    	return 0;
    }
    
    
  • 相关阅读:
    前端知识点(1)
    js防抖和节流
    react生命周期方法有哪些?
    vue音乐播放器
    vue天气查询
    vue+axios安装
    vue 实现todolist,包含添加,删除,统计,清空,隐藏功能
    vue简单计数器
    手动搭建的react环境中,关于图片引入的问题
    promise封装ajax
  • 原文地址:https://www.cnblogs.com/Mychael/p/9036417.html
Copyright © 2011-2022 走看看