原题: http://codeforces.com/contest/1131/problem/E
题意:
定义字符串 S ∗ T = T + S 1 ( 第 一 个 字 母 ) + T + . . . + S n + T S*T=T+S_1(第一个字母)+T+...+S_n+T S∗T=T+S1(第一个字母)+T+...+Sn+T,例如 a c ∗ b = b a b c b ac*b=babcb ac∗b=babcb,现在给出n个串 P 1 . . . P n P_1...P_n P1...Pn,求目标串 ( . . ( P 1 ∗ P 2 ) ∗ P 3 ) . . . ) ∗ P n (..(P_1*P_2)*P_3)...)*P_n (..(P1∗P2)∗P3)...)∗Pn中,连续相同字符的个数的最大值( a b b b c = 3 abbbc=3 abbbc=3)。
解析:
可以分析出 ( . . ( P 1 ∗ P 2 ) ∗ P 3 ) . . . ) ∗ P n = P 1 ∗ ( . . . ( P n − 2 ∗ ( P n − 1 ∗ P n ) . . . ) (..(P_1*P_2)*P_3)...)*P_n=P_1*(...(P_{n-2}*(P_{n-1}*P_n)...) (..(P1∗P2)∗P3)...)∗Pn=P1∗(...(Pn−2∗(Pn−1∗Pn)...),即先从后面处理,这样有什么好处? S ∗ T S*T S∗T的意思其实是把 T T T插入到 S S S的各个位置,连接两块S的只有一个字符。这样最明显的优势为:只要 T T T已经非同一字符(至少两种字符),那么 S ∗ T S*T S∗T的左端连续相同字符和右端连续字符,不管在种类上还是长度上都和 T T T一样。
考虑可能变长的部分:
如果两边字符相同且等于x,那么长度为l+1+r。其他情况可自行考虑。
如果一直相同更好办, s u m ( 已 积 累 长 度 ) = l e n ( 当 前 段 长 度 ) + ( l e n + 1 ) ∗ s u m sum(已积累长度)=len(当前段长度)+(len+1)*sum sum(已积累长度)=len(当前段长度)+(len+1)∗sum。
注意点:
- 需要用最后一个串的最长连续相同子串更新答案。
- 第一次出现不同时,假设累积串为 a a a aaa aaa,当前串为 b a a b baab baab,那么 a a a ∣ a ∣ a a a ∣ a ∣ a a a aaa|a|aaa|a|aaa aaa∣a∣aaa∣a∣aaa需要更新答案。
代码:
#include<bits/stdc++.h>
using namespace std;
string x[100009];
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i];
}
int l=0,r=0;
int ans=1;
char L=x[n][0],R=x[n][x[n].length()-1];
//***************考虑第一个串
int co=1;
for(int i=1;i<x[n].length();i++){
if(x[n][i]==x[n][i-1])co++;
else {
ans=max(ans,co);
co=1;
}
}
ans=max(ans,co);
int sum=0;
if(x[n].length()==1){
sum=1;
}
else{
int i;
for(i=1;i<x[n].length();i++){
if(x[n][i]!=x[n][0])break;
}
i--;
if(i==x[n].length()-1){
sum=x[n].length();
}
else{
l=i+1;
for(i=x[n].length()-2;;i--){
if(x[n][i]!=R)
break;
}
r=x[n].length()-1-i;
}
}
ans=max(ans,max(sum,max(l,r)));
//***************
for(int i=n-1;i>=1;i--){
if(!l){//还是全部相同
int f=0;
for(int j=0;j<x[i].length();j++){
if(x[i][j]!=L){
f=1;
l=j+(j+1)*sum;
break;
}
}
if(f){
for(int j=x[i].length()-1;;j--){
if(x[i][j]!=R){
r=x[i].length()-1-j;
r=r+(r+1)*sum;
break;
}
}
//第一次出现不同时
int co=0;
for(int j=0;j<x[i].length();j++){
if(x[i][j]==L)co++;
else {
ans=max(ans,co+(co+1)*sum);
co=0;
}
}
ans=max(ans,co+(co+1)*sum);
}
else{
sum=x[i].length()+(x[i].length()+1)*sum;
}
}
else{
for(int j=0;j<x[i].length();j++){
if(x[i][j]==L){
if(L==R){
ans=max(ans,l+r+1);
}
else{
ans=max(ans,l+1);
}
}
else if(x[i][j]==R){
ans=max(ans,r+1);
}
}
}
}
ans=max(ans,max(sum,max(l,r)));
printf("%d\n",ans);
}