首页 > 洛谷 3519 bzoj 2213 Difference

洛谷 3519 bzoj 2213 Difference

联考考试考到了这个题,随机化40分,现在来秒掉它吧。

 

题意:

给一个字符串,求其中的一段,使得出现次数最多的字符与出现次数最少的字符的出现次数之差最大。

输入输出样例

输入样例#1: 复制
10
aabbaaabab
输出样例#1: 复制
3

 

我们定义$cnt[i][j]$表示区间$[1,i]$中,j出现的次数,

定义字符a,b(非字符a,b),a为出现最多的字符,b为出现最少的字符。

我们利用前缀和统计每一个字符出现的次数。

那么对于一个区间$[i,j]$,字符a出现的次数为$cnt[j][a]-cnt[i][a]$,字符b出现的次数为$cnt[j][b]-cnt[i][b]$,我们枚举每一个字符的配对情况。

对于26个字符$$ans=max { ans,(cnt[j][a]-cnt[i][a])-(cnt[j][b]-cnt[i][b]) }$$。

这样枚举时间复杂度$O(n^2 imes 26 imes 26)$,还可以啦。

现在我们来优化一下上边的过程。

$$(cnt[j][a]-cnt[i][a])-cnt[j][b]-(cnt[i][b])$$

可以变为

$$(cnt[j][a]-cnt[j][b])-(cnt[i][a]-cnt[i][b])$$

对于算式的前半边O(n imes 26)枚举,我们来优化一下后半边。

对于后边的式子,求得为j以前$cnt[i][a]-cnt[i][b]$的最小值,然而j是怎么过来的,到了j必然前边的数都有经过,所以我们在枚举是维护一个$cnt[i][a]-cnt[i][b]$的最小值即可(代码中用到minv数组)。

代码中有p[i][j]数组表示更新字符i和字符j差的最小值的位置。

总的时间复杂度$O(n imes 26)$

 

#include
#include
using namespace std;
const int N=1e6+7,M=27;
int n,ans;
int last[M],num[M],p[M][M],minv[M][M];
/* last表示字符最后出现的位置,num表示字符出现的次数。
p数组表示更新维护最小值的位置,minv表示维护的最小值。*/
char s[N];
int main()
{
//    freopen("B.in","r",stdin);
//    freopen("B.out","w",stdout);scanf("%d%s",&n,s+1);for(int i=1; i<=n; i++){int c=s[i]-'a';num[c]++;last[c]=i;for(int j=0; j<26; j++)if(j!=c && num[j])ans=max(ans,max(num[c]-num[j]-minv[c][j]-(last[j]==p[c][j]),num[j]-num[c]-minv[j][c]-(last[c]==p[j][c])));/*最后出现的位置与最小值更新的位置相等,那么在我们判断的区间里,不会出现j,对于这段区间-j,就等于只是选定区间内c出现的次数,这是不符合条件的,那么要让他更大,再向左选一个不同的字符那么tot[u]-1一定是最优的。*/for(int j=0; j<26; j++)if(num[j]-num[c]<minv[j][c]){minv[j][c]=num[j]-num[c];p[j][c]=i;}//更新最小值。
    }printf("%d
",ans);
//    fclose(stdin);fclose(stdout);return 0;
}

 

转载于:https://www.cnblogs.com/rmy020718/p/9615482.html

更多相关:

  • 1. 三字母词 在C语言中有一种三字母词的说法,trigraph sequences,目前为止有九种三字母词,如下 ??=               #                  ??)            ]                  ??!           |         ??(      ...

  • 题目:   请你来实现一个 atoi 函数,使其能将字符串转换成整数。   首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。   当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组...

  • 本推文主要识别的验证码是这种:第一步: 二值化所谓二值化就是把不需要的信息通通去除,比如背景,干扰线,干扰像素等等,只剩下需要识别的文字,让图片变成2进制点阵。第二步: 文字分割为了能识别出字符,需要对要识别的文字图图片进行分割,把每个字符作为单独的一个图片看待。第三步: 标准化对于部分特殊的验证码,需要对分割后的图片进行标准化处理,...

  •   源字符串: a a 1 ~`!@#$%^&()_+-={}[];',.- + 编码后: a%20a%201%20~%60%21@%23$%25%5E&%28%29_+-=%7B%7D%5B%5D;%27,.-%20+   源字符串: 变 ~!@#¥%…………&()——+=-·{}:“;‘、《》?,。、-+A a 1 编码后:...

  • 语言:c#  问题:偶尔会出现连不上mysql 报标题的这个错误。   解决方法:把server = localhost 改为 =127.0.0.1 或者静态IP  ,按着改暂时没出现了,继续观望!   转载于:https://www.cnblogs.com/wdw31210/p/9857514.html...

  • 这题 做出来真的好爽啊... it is cool  although it is easy 虽然 已经是大概1 2点的事了 我拖到现在才写是因为------lol 终于赢一把了 --- 先贴下题目:   touch me 嗯  我一开始 用的是 3重for 我以为32767的数据量 是很小的....   结果 TLE。。 OK 那么...