CF1131E String Multiplication

題面
英文題面
題意:定義兩個字符串\(s\)\(t\)\(s\)的長度爲\(m\))的乘積爲: \(t+s_1+t+s_2+\dots+t+s_m+t\)
定義一個字符串的美麗度爲最長的相同字母連續子序列的長度。如今給出\(n\)個字符串\(p_i\) ,問
\(((p_1p_2)p_3)\dots p_n\)的美麗度。
\(|s|,|t|,n,\sum p_i \leq 10^5\)
題解:
對每一個字母分別考慮。設最後一個串爲\(S\)
發現答案只多是\(S\)的一個子串,或是\(S\)的一段前綴和後綴,或是若干個完整的\(S\)拼接起來。
對於第一種狀況,直接掃一遍就好了。
對於後兩種狀況,因爲前\(n-1\)個串最後都得分開,它們只能做爲鏈接兩個或若干個\(S\)的鏈接字符。
那麼對於第二種狀況,顯然貢獻就是\(S\)的一段後綴+1+\(S\)的一段前綴。
對於第三種狀況,也就是當前串全部字符都爲指定的字符時,咱們須要維護以前的操做獲得的串的最長連續字符個數。
設以前的最長連續字符數爲\(sum\),當前\(t\)串的長度爲\(len\),那麼操做後獲得的最長連續字符個數即爲:\(len*(sum+1)+sum\)
時間複雜度:\(O(\sum p_i)\)
代碼:ios

#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
char s[101000];
vector<int>c[101000];
int n,m,ans,len[101000],pre[101000],suf[101000],mx[101000],cnt;
I solve(int x){
	F(i,1,n){
		pre[i]=0;
		while(pre[i]<len[i]&&c[i][pre[i]+1]==x)pre[i]++;
		suf[i]=0;
		while(suf[i]<len[i]&&c[i][len[i]-suf[i]]==x)suf[i]++;
		mx[i]=cnt=0;
		F(j,1,len[i]){
			if(c[i][j]==x)cnt++;
			else cnt=0;
			mx[i]=max(mx[i],cnt);
		}
//		cout<<pre[i]<<" "<<suf[i]<<" "<<mx[i]<<endl;
//		ans=max(ans,mx[i]);
	}
	ans=max(ans,mx[n]);
	re num=mx[1];
	F(i,2,n){
		if(pre[i]==len[i]){
			if(num)num+=(len[i]*(num+1));
			else num=len[i];
		}
		else num?num=pre[i]+suf[i]+1:num=max(pre[i],suf[i]);
		num=max(num,mx[i]);
//		cout<<num<<endl;
	}
	ans=max(ans,num);
//	cout<<endl;
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n;
	F(i,1,n){
		cin>>s+1;len[i]=strlen(s+1);c[i].resize(len[i]+1);
		F(j,1,len[i])c[i][j]=s[j]-'a'+1;
	}
	F(t,1,26)solve(t);
	cout<<ans;
	return 0;
}
相關文章
相關標籤/搜索