BZOJ2213 : [Poi2011]Difference

设f[i][j]为前i个字符中j出现的次数,则

ans=max((f[r][i]-f[l-1][i])-(f[r][j]-f[l-1][j]))=max((f[r][i]-f[r][j])-(f[l-1][i]-f[l-1][j])),其中f[r][j]!=f[l-1][j]。

考虑枚举r,当r从r-1变化到r时,f[r][i]-f[r][j]与f[r-1][i]-f[r-1][j]只有52个值会改变。

处理这52组(i,j),并求出min(f[l-1][i]-f[l-1][j])。

因为要满足f[r][j]!=f[l-1][j],所以要记录f[x][i]-f[x][j]的最小值和次小值及其对应的f[x][j],且要保证f[x][j]不相同。

若最小值对应的f[x][j]!=f[r][j],则取最小值,否则取次小值。

时间复杂度$O(26n)$。

 

#include<cstdio>
#define K 26
int n,i,j,k,c[K],b[K][K],f0[K][K],g0[K][K],f1[K][K],g1[K][K],ans;char a[1000010];
inline void max(int x){if(ans<x)ans=x;}
inline void up(int j,int k){
  if(g0[j][k]!=c[k])max(b[j][k]-f0[j][k]);else if(g1[j][k]!=c[k])max(b[j][k]-f1[j][k]);
  if(b[j][k]<f0[j][k]){
    if(c[k]!=g0[j][k])f1[j][k]=f0[j][k],g1[j][k]=g0[j][k];
    f0[j][k]=b[j][k],g0[j][k]=c[k];
  }else if(c[k]!=g0[j][k]&&b[j][k]<=f0[j][k])f1[j][k]=b[j][k],g1[j][k]=c[k];
}
int main(){
  scanf("%d",&n),gets(a),gets(a+1);
  for(i=1;i<=n;i++)for(c[j=a[i]-'a']++,k=0;k<26;k++)if(k!=j)b[j][k]++,up(j,k),b[k][j]--,up(k,j);
  return printf("%d",ans),0;
}

  

posted @ 2015-08-06 00:49  Claris  阅读(605)  评论(0编辑  收藏  举报