题面
英文题面
题意:定义两个字符串\(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; }