顯然全部相同的可以O(N)掃一遍得到,那麼不妨考慮不存在某兩種字母相同的最長長度。
令x[i]為1~i中‘B’的個數,y[i]為'C'的個數,z[i]為‘S’的個數。那麼某一段i+1~j,不符合題設的條件為:
x[i]-x[j]=y[i]-y[j]或x[i]-x[j]=z[i]-z[j]或y[i]-y[j]=z[i]-z[j]。
如果把與i相關的移到一邊,然後每個點相當於一個三元組(x[i]-y[i],y[i]-z[i],z[i]-x[i]),然後如果一對u,v(u<v),使得三元組的每一個元素兩兩不同,那麼就用v-u更新答案。
第一維排序;然後以第二維為下標維護樹狀數組,儲存最大值,最大值的第三維;和最大值的第三維不同的最大值。還有最小值。
實際上可以不用樹狀數組,直接整體二分也可以。
時間複雜度O(NlogN)。注意常數。
AC代碼如下:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define inf 1000000000#define N 1000005using namespace std;int n,cnt,ans,tot,fst[N<<1],pnt[N],nxt[N]; struct node{ int x,y,z,id; }a[N],c[N][2];bool cmpx(node u,node v){ return u.x<v.x; }bool cmpy(node u,node v){ return u.y<v.y; }void add(int x,int y){pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;}void dn(node &u,int x,int y){if (x<u.x){if (y==u.y) u.x=x; else{ u.z=u.x; u.x=x; u.y=y; }} else if (y!=u.y) u.z=min(u.z,x);}void up(node &u,int x,int y){if (x>u.x){if (y==u.y) u.x=x; else{ u.z=u.x; u.x=x; u.y=y; }} else if (y!=u.y) u.z=max(u.z,x);}void qry(int x,int k,int y){for (; x; x-=x&-x){if (c[x][0].y==y) ans=max(ans,k-c[x][0].z); else ans=max(ans,k-c[x][0].x);if (c[x][1].y==y) ans=max(ans,c[x][1].z-k); else ans=max(ans,c[x][1].x-k);}}void mdy(int x,int k,int y){for (; x<=cnt; x+=x&-x){dn(c[x][0],k,y); up(c[x][1],k,y);}}void solve(){int i,j,k;for (i=1; i<=cnt; i++){c[i][0].x=c[i][0].z=inf; c[i][1].x=c[i][1].z=-inf;}for (i=1; i<=(n<<1|1); i++){for (j=fst[i]; j; j=nxt[j]){k=pnt[j]; qry(a[k].y-1,a[k].id,a[k].z);}for (j=fst[i]; j; j=nxt[j]){k=pnt[j]; mdy(a[k].y,a[k].id,a[k].z);}}}int main(){scanf("%d",&n); int i,p,t=0;char ch=getchar(),lastch='A';while (ch<'A' || ch>'Z') ch=getchar();for (i=1; i<=n; i++){if (ch==lastch) t++; else t=1; ans=max(ans,t);a[i]=a[i-1]; a[i].id=i;if (ch=='B'){ a[i].x++; a[i].z--; } elseif (ch=='C'){ a[i].y++; a[i].x--;} else{ a[i].z++; a[i].y--; }if (i<n){ lastch=ch; ch=getchar(); }}for (i=0; i<=n; i++) add(a[i].y+n+1,i);for (i=1; i<=(n<<1|1); i++) if (fst[i]){cnt++;for (p=fst[i]; p; p=nxt[p]) a[pnt[p]].y=cnt;}tot=0; memset(fst,0,sizeof(fst));for (i=0; i<=n; i++) add(a[i].x+n+1,i);solve();for (i=0; i<=n; i++) a[i].y=cnt-a[i].y+1;solve();printf("%d\n",ans);return 0;}
by lych
2-16.4.2