1. 程式人生 > 其它 >ABC 213 F Common Prefixes題解

ABC 213 F Common Prefixes題解

題意

給定一個長度為\(n\)的字串\(s\),設對於兩字串\(x\)\(y\)\(f(x,y)=\max\{k|1\le k\le \min(|x|,|y|)且\forall i\in [1,k]\cap N^*,x_i=y_i\}\)
\(S_i={s_is_{i+1}\cdots s_n}\)。對於每一個\(k\in [1,n]\cap N^*\),求\(\sum_{i=1}^nf(S_i,S_k)\)

思路

首先預處理出\(height\)陣列,\(h[i]=lcp(suf_{sa_i},suf_{sa_{i-1}})\)
有結論:\(lcp(suf_i,suf_j)(rnk_i<rnk_j)=\min_{k=rnk_i+1}^{rnk_j}h_k\)


此時,題目轉換為:給出一長度為\(n\)的序列\(a_1,a_2,\cdots,a_n\),要求對每一個\(i\)求出\(\sum_{i=1}^n\min_{k=\min(i,j)}^{\max(i,j)}a_k\)
這個問題可以用單調棧輕鬆求出。
總時間複雜度:\(O(n+SA(n))\),其中\(SA(n)\)表示求字尾陣列所需要的時間。

程式碼

using namespace std;
typedef long long ll;
const int mod=998244353;
int fir[2000005],rnk[2000005],sa[2000005],sec[2000005],s[2000005],h[2000005];
int st[2000005],top;
ll val[2000005],ans[2000005];
char str[2000005];
void MakeSA(int n,int m){
	int *x=rnk,*y=sec;
	for(int i=1;i<=n;i++)s[x[i]=str[i]-'a'+1]++;
	for(int i=1;i<=m;i++)s[i]+=s[i-1];
	for(int i=n;i;i--)sa[s[x[i]]--]=i;
	for(int j=1,p=0;p<n?(p=0,1):0;j<<=1,m=p){
		for(int i=n-j+1;i<=n;i++)y[++p]=i;
		for(int i=1;i<=n;i++)if(sa[i]>j)y[++p]=sa[i]-j;
		for(int i=1;i<=m;i++)s[i]=0;
		for(int i=1;i<=n;i++)s[fir[i]=x[y[i]]]++;
		for(int i=1;i<=m;i++)s[i]+=s[i-1];
		for(int i=n;i;i--)sa[s[fir[i]]--]=y[i];
		swap(x,y),x[sa[p=1]]=1;
		for(int i=2;i<=n;i++)x[sa[i]]=(p+=(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+j]!=y[sa[i-1]+j]));
	}
	for(int i=1;i<=n;i++)rnk[sa[i]]=i;
	for(int i=1,j=0;i<=n;i++){
		if(rnk[i]==1)h[rnk[i]]=0;
		else {
			j=max(j-1,0);
			while(str[i+j]==str[sa[rnk[i]-1]+j])j++;
			h[rnk[i]]=j;
		}
	}
	top=0,st[0]=1;
	for(int i=2;i<=n;i++){
		while(top&&h[st[top]]>=h[i])top--;
		st[++top]=i,val[top]=val[top-1]+1ll*(i-st[top-1])*h[i];
		ans[i]+=val[top];
	}
	top=0,st[0]=n+1;
	for(int i=n;i>=2;i--){
		while(top&&h[st[top]]>=h[i])top--;
		st[++top]=i,val[top]=val[top-1]+1ll*(st[top-1]-i)*h[i];
		ans[i-1]+=val[top];
	}
	for(int i=1;i<=n;i++)printf("%lld\n",ans[rnk[i]]+(n-i+1));
}
int main(){
	int n;
	cin>>n>>str+1;
	MakeSA(n,26);
}

本文來自部落格園,作者:jpy_cpp,轉載請註明原文連結:https://www.cnblogs.com/jpy-cpp/p/15122798.html