1. 程式人生 > >BZOJ3230 相似子串 【後綴數組】

BZOJ3230 相似子串 【後綴數組】

ostream getchar() pair HA AI set gets cst rep

題目鏈接

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\n",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; }

BZOJ3230 相似子串 【後綴數組】