BZOJ_3879_SvT_後綴數組+單調棧
阿新 • • 發佈:2018-05-23
可能 font IT uil stat -- prefix using div
popoqqq
1 4
2 3 5
4 1 2 5 6
BZOJ_3879_SvT_後綴數組+單調棧
Description
(我並不想告訴你題目名字是什麽鬼)
有一個長度為n的僅包含小寫字母的字符串S,下標範圍為[1,n].
現在有若幹組詢問,對於每一個詢問,我們給出若幹個後綴(以其在S中出現的起始位置來表示),求這些後綴兩兩之間的LCP(LongestCommonPrefix)的長度之和.一對後綴之間的LCP長度僅統計一遍.
Input
第一行兩個正整數n,m,分別表示S的長度以及詢問的次數.
接下來一行有一個字符串S.
接下來有m組詢問,對於每一組詢問,均按照以下格式在一行內給出:
首先是一個整數t,表示共有多少個後綴.接下來t個整數分別表示t個後綴在字符串S中的出現位置.
Output
對於每一組詢問,輸出一行一個整數,表示該組詢問的答案.由於答案可能很大,僅需要輸出這個答案對於23333333333333333(一個巨大的質數)取模的余數.Sample Input
7 3popoqqq
1 4
2 3 5
4 1 2 5 6
Sample Output
0
0
2
類似http://www.cnblogs.com/suika/p/8995997.html這道題,只不過本題變成了給定多個後綴的LCP。
先求出height數組,然後建立ST,設g[i]表示給出的第i個後綴到第i+1個後綴的LCP長度。
轉化為求所有區間最小值之和。
dp[i]表示以第i個位置為結尾的所有區間最小值之和,對於i左邊第一個大於等於g[i]的g[j],有f[i]=f[j]+(i-j)*g[i],答案就是dp[i]之和。
然後隨便卡卡就BZrk2了。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define RR register __attribute__((optimize("-O2")))inline char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } __attribute__((optimize("-O2")))inline int rd() { int x=0; RR char c=nc(); while(c<‘0‘||c>‘9‘) c=nc(); while(c>=‘0‘&&c<=‘9‘) x=(x<<3)+(x<<1)+c-‘0‘,c=nc(); return x; } __attribute__((optimize("-O2")))inline int rc() { char c=nc(); while(c<‘a‘||c>‘z‘) c=nc(); return (int)c; } #define N 500050 typedef long long ll; int n,m,wa[N],wb[N],wv[N],sa[N],height[N],rank[N],r[N],ws[N]; char ch[N]; int f[21][N],L[N],vis[N],s[N],g[N]; int v[3000050],Q[3000050]; ll dp[N]; __attribute__((optimize("-O2")))void build_sa_array() { m=27; int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[x[i]]]=i; for(p=j=1;p<n;j<<=1,m=p) { for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]-j>=0) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; for(t=x,x=y,y=t,i=p=1,x[sa[0]]=0;i<n;i++) { if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1; else x[sa[i]]=p++; } } for(i=1;i<n;i++) rank[sa[i]]=i; for(i=p=0;i<n-1;height[rank[i++]]=p) for(p?p--:0,j=sa[rank[i]-1];r[i+p]==r[j+p];p++); } __attribute__((optimize("-O2")))int get_min(int l,int r) { int len=L[r-l+1]; return min(f[len][l],f[len][r-(1<<len)+1]); } __attribute__((optimize("-O2")))void ST() { int i,j; for(i=2;i<=n;i++) L[i]=L[i>>1]+1; for(i=1;i<=n;i++) f[0][i]=height[i]; for(i=1;(1<<i)<=n;i++) { for(j=1;j+(1<<i)-1<=n;j++) { f[i][j]=min(f[i-1][j],f[i-1][j+(1<<(i-1))]); } } } __attribute__((optimize("-O2")))bool cmp(int x,int y) { return rank[x]<rank[y]; } char pbuf[10000000] , *pp = pbuf; __attribute__((optimize("-O2")))void write(int x) { static int sta[35]; int top = 0; if(!x)sta[++top]=0; while(x) sta[++top] = x % 10 , x /= 10; while(top) *pp ++ = sta[top -- ] ^ ‘0‘; } __attribute__((optimize("-O2")))int main() { int T; n=rd(); T=rd(); RR int i; for(i=0;i<n;i++) r[i]=rc()-‘a‘+1; r[n++]=0; int tot=0; build_sa_array(); n--; ST(); while(T--) { tot++; int t=0; v[0]=rd(); RR int j; for(j=1;j<=v[0];j++) { v[j]=rd(); v[j]--; if(vis[v[j]]==tot) { j--; v[0]--; } vis[v[j]]=tot; } sort(v+1,v+v[0]+1,cmp); for(j=1;j<v[0];j++) { g[j]=get_min(rank[v[j]]+1,rank[v[j+1]]); } t=1; Q[1]=0; long long ans=0; for(j=1;j<v[0];j++) { while(t&&g[Q[t]]>g[j]) t--; dp[j]=dp[Q[t]]+1ll*(j-Q[t])*g[j]; ans+=dp[j]; Q[++t]=j; } write(ans);*pp++=‘\n‘; } fwrite(pbuf , 1 , pp - pbuf , stdout); }
BZOJ_3879_SvT_後綴數組+單調棧