1. 程式人生 > 實用技巧 >CF356E Xenia and String Problem

CF356E Xenia and String Problem

英文題面

題意:給定一個字串\(S\)。定義一個字串\(t\)是"gray"串,當且僅當:

  • \(|t|\)是奇數;
  • \(mid=(1+|t|)/2\),則\(t_{mid}\)僅在\(t\)中出現一次;
  • \(t_{1,\cdots mid-1}\)\(t_{mid+1,\cdots |t|}\)相同,且都為gray串。

定義一個串\(t\)的美麗度為:\(\sum_{l,r} (r-l+1)^2 \times [t_{l,\cdots r}是gray串]\)

你可以修改\(S\)的一個字元,當然也可以不修改。求修改後的\(S\)的美麗度的最大值。

題解:

\(n=|S|\)

。考慮到gray串的長度為\(2^k -1\),所以gray串的總數是\(nlogn\)級別的。

先考慮如何求出所有的gray串。我們可以做一個類似求st表的東西,設\(g_{i,j}\)表示以\(i\)為左端點,長度為\(2^j -1\)的串是否為gray串。可以通過字串雜湊或者字尾陣列求得兩邊的串是否相同。然後對於第二個限制,記一個字首和陣列\(s_{i,j}\)表示字元\(j\)\([1,i]\)中的出現次數就行了。

再考慮改變一個字元對美麗度的影響。我們可以看作是將其刪除,然後再加入。刪除的過程中,所有包含當前點的子串的貢獻都需要被減去。這個只需要開一個數組,在算上面的東西的同時維護一下。由於是區間加,用差分就好了。

對於將其加入後如何算新的貢獻,我們可以再列舉左端點以及其對應的右端點,進行分類討論。設當前的區間為\([l,r]\),中間點為\(md\),當前長度為\(len_j=2^j-1\)\(lcp\)\(s_{l,\cdots md-1}\)\(s_{md+1,\cdots r}\)\(lcp\)

  1. \(g_{l,j-1}=1,g_{md+1,j-1}=1,lcp=len_{j-1}\),我們只需要考慮第二個限制,列舉\(s_{md}\)可以是哪個字元即可;
  2. \(g_{l,j-1}=1,g_{md+1,j-1}=1,_l=len_{j-1}\),這種情況下\(lcp\)必須等於\(len_{j-2}\)
    ,也就是說,只允許\(s_{l+len_{j-2}}\neq s_{md+1+len_{j-2}}\),否則這個串就沒有貢獻。所以此時我們判一下將這兩個字元中的一個改為另一個之後這個串是否合法就行了;
  3. \(g_{l,j-1}+g_{md+1,j-1}=1\),此時我們只允許\(s_{l+lcp}\neq s_{md+1+lcp}\),所以再求一下這兩個位置後面的\(lcp\),判一下,然後看能不能把不為gray串的那邊的那個不一樣的字元換成是gray串的那邊對應的字元即可。
  4. 其餘情況都無法產生貢獻。

我們將上述操作的過程用一個數組\(con_{i,j}\)記錄下來即可。剩下的東西就很好做了。

時間複雜度:\(O(nlogn \times 26)\),當然肯定不會跑滿。建議用sa求lcp,可以少一個二分的log。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
char c[101000];
int n,m,mx,val,ln[30],s[101000][30],g[101000][20],a[101000],sa[101000],tp[101000],buc[101000],tot,rk[101000],hei[101000],f[101000][20],lg[101000];
ll w[101000],ans,sum,con[101000][30];
I build_sa(){
	m=30;
	F(i,1,n)buc[rk[i]=a[i]]++;
	F(i,1,m)buc[i]+=buc[i-1];
	FOR(i,n,1)sa[buc[rk[i]]--]=i;
	for(re k=1;k<=n;k<<=1){
		re tot=0;
		F(i,n-k+1,n)tp[++tot]=i;
		F(i,1,n)if(sa[i]>k)tp[++tot]=sa[i]-k;
		F(i,1,m)buc[i]=0;
		F(i,1,n)buc[rk[i]]++;
		F(i,1,m)buc[i]+=buc[i-1];
		FOR(i,n,1)sa[buc[rk[tp[i]]]--]=tp[i],tp[i]=0;
		swap(rk,tp);
		rk[sa[1]]=tot=1;
		F(i,2,n)rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+k]==tp[sa[i]+k])?tot:++tot;
		if(tot==n)break;
		m=tot;
	}
	re k=0;
	F(i,1,n){
		if(rk[i]==1)continue;
		if(k)k--;
		re p=sa[rk[i]-1];
		while(a[i+k]==a[p+k])k++;
		hei[rk[i]]=k;
	}
	lg[0]=-1;F(i,1,n)f[i][0]=hei[i],lg[i]=lg[i>>1]+1;
	F(j,1,lg[n])F(i,1,n-(1<<j)+1)f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
IN ques_lcp(int x,int y){
	if(x==y)return n-x+1;x=rk[x];y=rk[y];if(x>y)swap(x,y);x++;
	re len=lg[y-x+1];return min(f[x][len],f[y-(1<<len)+1][len]);
}
int main(){
	ios::sync_with_stdio(false);
	cin>>c+1;n=strlen(c+1);
	F(i,1,n)a[i]=c[i]-'a'+1;
	build_sa();
	F(i,1,n){
		F(j,1,26)s[i][j]=s[i-1][j];
		s[i][a[i]]++;
	}
	F(i,1,n)g[i][1]=1;w[1]=1;
	re l,r,md,_l,_r,sn;mx=lg[n]+1;ans=n;
	F(i,1,mx)ln[i]=(1<<i)-1;
	F(j,2,mx)F(i,1,n-(1<<j)+2){
		l=i;r=i+(1<<j)-2;md=(l+r)>>1;
		if(!g[i][j-1]||!g[md+1][j-1]||ques_lcp(l,md+1)<ln[j-1]||s[r][a[md]]-s[l-1][a[md]]>1)continue;
		g[i][j]=1;w[l]+=(ll)ln[j]*ln[j];w[r+1]-=(ll)ln[j]*ln[j];ans+=(ll)ln[j]*ln[j];
	}
	F(i,2,n)w[i]+=w[i-1];
	F(i,1,n)F(j,1,26)con[i][j]=1;
	F(j,2,mx)F(i,1,n-(1<<j)+2){
		l=i;r=i+(1<<j)-2;md=(l+r)>>1;_l=ques_lcp(l,md+1);
		if(g[i][j-1]&&g[md+1][j-1]){
			if(_l>=ln[j-1]){
				F(k,1,26)if(s[r][k]==s[l-1][k])con[md][k]+=(ll)ln[j]*ln[j];
				continue;
			}
			if(_l<ln[j-2])continue;
			val=a[l+ln[j-2]];if(a[r-ln[j-2]]==a[md])sn=1;else if(val==a[md])sn=-1;else sn=0;
			if(s[r][a[md]]-s[l-1][a[md]]-sn==1)con[r-ln[j-2]][val]+=(ll)ln[j]*ln[j];
			val=a[r-ln[j-2]];if(a[l+ln[j-2]]==a[md])sn=1;else if(val==a[md])sn=-1;else sn=0;
			if(s[r][a[md]]-s[l-1][a[md]]-sn==1)con[l+ln[j-2]][val]+=(ll)ln[j]*ln[j];
			continue;
		}
		if(!g[i][j-1]&&!g[md+1][j-1])continue;
		if(g[i][j-1]){
			_r=ques_lcp(l+_l+1,md+_l+2);if(_l+_r+1<ln[j-1])continue;
			val=a[l+_l];if(a[md+1+_l]==a[md])sn=1;else if(val==a[md])sn=-1;else sn=0;
			if(s[r][a[md]]-s[l-1][a[md]]-sn==1)con[md+1+_l][val]+=(ll)ln[j]*ln[j];
		}
		if(g[md+1][j-1]){
			_r=ques_lcp(l+_l+1,md+_l+2);if(_l+_r+1<ln[j-1])continue;
			val=a[md+1+_l];if(a[l+_l]==a[md])sn=1;else if(val==a[md])sn=-1;else sn=0;
			if(s[r][a[md]]-s[l-1][a[md]]-sn==1)con[l+_l][val]+=(ll)ln[j]*ln[j];
		}
	}
	sum=0;
	F(i,1,n)F(j,1,26)if(a[i]^j)sum=max(sum,con[i][j]-w[i]);
	ans+=sum;cout<<ans;
	return 0;
}