bzoj千題計劃314:bzoj3238: [Ahoi2013]差異(字尾陣列+st表+單調棧)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int n,m,mm; char s[N]; int a[N]; int v[N]; int p,q=1,k; int sa[2][N],rk[2][N]; int h[N]; int st[N][16]; int Log[N]; int ST[N],top; int num[N],val[N];void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void mul(int *sa,int *rk,int *SA,int *RK) { for(int i=1;i<=n;++i) v[rk[sa[i]]]=i; for(int i=n;i;--i) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k;for(int i=n-k+1;i<=n;++i) SA[v[rk[i]]--]=i; for(int i=1;i<=n;++i) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]] || rk[SA[i]+k]!=rk[SA[i-1]+k]); } void presa() { for(int i=1;i<=n;++i) v[a[i]]++; for(int i=1;i<=26;++i) v[i]+=v[i-1]; for(int i=1;i<=n;++i) sa[p][v[a[i]]--]=i;for(int i=1;i<=n;++i) rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]); for(k=1;k<n;k<<=1,swap(p,q)) mul(sa[p],rk[p],sa[q],rk[q]); } void get_height() { int k=0,j; for(int i=1;i<=n;++i) { j=sa[p][rk[p][i]-1]; while(a[i+k]==a[j+k]) k++; h[rk[p][i]]=k; if(k) k--; } } void prest() { for(int i=2;i<=n;++i) st[i][0]=h[i]; for(int i=1,k=2;i<=15;++i,k<<=1) for(int j=2;j+k-1<=n;++j) st[j][i]=min(st[j][i-1],st[j+k/2][i-1]); } int get(int i,int j) { i++; int l=Log[j-i+1]; return min(st[i][l],st[j-(1<<l)+1][l]); } void solve() { top=0; int tmp_num; long long now=0,ans=0; for(int i=2;i<=n;++i) { tmp_num=0; while(top && h[i]<=h[ST[top]]) { now-=1LL*num[top]*val[top]; tmp_num+=num[top--]; } tmp_num++; ST[++top]=i; num[top]=tmp_num; val[top]=h[i]; now+=1LL*tmp_num*h[i]; ans+=now; } ans=-ans*2; ans+=1LL*n*(n+1)/2*(n-1); cout<<ans<<'\n'; } int main() { scanf("%s",s+1); n=strlen(s+1); for(int i=2;i<=n;++i) Log[i]=Log[i>>1]+1; for(int i=1;i<=n;++i) a[i]=s[i]-'a'+1; presa(); get_height(); prest(); solve(); }
相關推薦
bzoj千題計劃314:bzoj3238: [Ahoi2013]差異(字尾陣列+st表+單調棧)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int n
bzoj千題計劃313:bzoj3879: SvT(字尾陣列+st表+單調棧)
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 500001 #define M 3000001 int n,m,mm;
bzoj千題計劃319:bzoj2865: 字串識別(字尾自動機 + 線段樹)
#include<map> #include<cstdio> #include<cstring> #include<algorithm> #define N 500001 using namespace std; char s[
bzoj千題計劃311:bzoj5017: [Snoi2017]炸彈(線段樹優化tarjan構圖)
#include<cstdio> #include<vector> #include<iostream> #include<algorithm> using namespace std; const int mod=1e9+7;
bzoj千題計劃308:bzoj4589: Hard Nim(倍增FWT+生成函式)
#include<cstdio> #include<cstring> using namespace std; #define N 50001 const int mod=1e9+7; const int M=1<<16; int inv
bzoj千題計劃315:bzoj3172: [Tjoi2013]單詞(AC自動機)
#include<queue> #include<cstdio> #include<cstring> using namespace std; #define N 2000001 using namespace std; int pos[20
BZOJ3238: [Ahoi2013]差異(字尾陣列)
Description Input 一行,一個字串S Output 一行,一個整數,表示所求值 Sample Input cacao Sample Output 54 解題思路: 看到lcp,想到了height陣列,沒錯,這道題是一道字尾陣列
bzoj千題計劃310:bzoj5285: [Hnoi2018]尋寶遊戲(思維題+雜湊)
#include<cstdio> #include<algorithm> #define N 5001 using namespace std; const int mod=1e9+7; int bit[N]; char s[N]; int has
bzoj千題計劃316:bzoj3173: [Tjoi2013]最長上升子序列(二分+樹狀陣列)
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 #define lowbit(x) x&-x
bzoj千題計劃309:bzoj4332: JSOI2012 分零食(分治+FFT)
#include<cmath> #include<cstdio> #include<algorithm> using namespace std; const int M=1<<17; #define N 10001 int m,
bzoj千題計劃321:bzoj5251: [2018多省省隊聯測]劈配(網路流 + 二分)
#include<queue> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #d
bzoj千題計劃312:bzoj2119: 股市的預測(字尾陣列+st表)
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #d
bzoj千題計劃317:bzoj4650: [Noi2016]優秀的拆分(字尾陣列+差分)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 30002 using namespace std; int n;
bzoj千題計劃318:bzoj1396: 識別子串(字尾自動機 + 線段樹)
#include<cstdio> #include<cstring> #include<algorithm> #define N 100001 using namespace std; char s[N]; int ch[N<&
bzoj千題計劃323:bzoj1951: [Sdoi2010]古代豬文(Lucas+CRT+尤拉定理)
#include<cmath> #include<cstdio> #include<iostream> using namespace std; const int mod=999911659; const int phi=mod-1; typ
bzoj千題計劃322:bzoj2561: 最小生成樹(最小割)
#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std;
bzoj千題計劃324:bzoj5249: [2018多省省隊聯測]IIIDX(線段樹)
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 500001 int d[N
bzoj千題計劃320:bzoj4939: [Ynoi2016]掉進兔子洞(莫隊 + bitset)
#include<cmath> #include<cstdio> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> us
[bzoj3238][Ahoi2013]差異_字尾陣列_單調棧
差異 bzoj-3238 Ahoi-2013 題目大意:求任意兩個字尾之間的$LCP$的和。 註釋:$1\le length \le 5\cdot 10^5$。 想法: 兩個字尾之間的$LCP$和顯然不好求。 我們先構建字尾陣列。 那麼任意兩個字尾之間的$LCP$之和就是所有$sa$陣列上所有
洛谷4248 AHOI2013差異 (字尾陣列SA+單調棧)
題目連結 補部落格! 首先我們觀察題目中給的那個求\(ans\)的方法,其實前兩項沒什麼用處,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); 那麼我們考慮剩下的部分應該怎麼求解! 首先這裡有一個性質。對於任意兩個字尾\(i,j\),他們的