a

【问题描述】
你是能看到第一题的 friends呢。
                                                         —— hja
何大爷对字符串十分有研究,于是天出题虐杀 zhx。何大爷今天为 何大爷今天为 字符串定义了新的权值计算方法。一个由小写母组成,被定义为其中出现次数最多的字符减去少。(注 被定义为其中出现次数最多的字符减去少。(注 意,在讨论出现最少的字符时候该必须至一次)何大爷给你一个字符串,何大爷想知道这的所有子中权值最是多少?
【输入格式】

第一行一个整数n,代表字符串的长度。
接下来一行n个小写字母,代表该字符串。
【输出格式】
一行个整数代表答案。
【样例输入】
10
aabbaaabab
【样例输出】
3

【数据范围与规定】

对于 30%的数据, 1≤n≤100。
对于 60%的数据, 1≤n≤1000。
对于 100%的数据, 1≤n≤106.

题目大意:

  求一个字符串子串的最多出现次数   减去    最少出现次数的 最大值

思路:

  1.爆搜

  2.正解:前缀和进行求解

    枚举右端点,使用前缀和优化。

    加入我们选定一段区间l~r,并且假设出现次数最多的为x,最少的为z,用一个数组sum[]统计一个字母到当前位置出现的次数,那么出现次数最多的字母与最少字母的差值显然为:

              sum[x][r]-sum[x][l-1]-(sum[z][r]-sum[z][l-1])  

            ==> sum[x][r]-sum[z][r]-sum[x][l-1]+sum[z][l-1]

            ==> (sum[x][r]-sum[z][r])-(sum[x][l-1]-sum[z][l-1])

    然后你可以发现:前面括号中的跟后面括号中的本质上是一个东西的,长的一毛一样,只是后面的区间端点不同而已。

    但是又因为l-1一定是比r要小的,所以l-1一定会在枚举r之前就已经被处理出来;

  所以现在我们需要知道的就只有x和z到底是谁就ok:

    我们枚举每一个点,然后再枚举另一个字母,处理出最大的sum[x][r]-sum[z][r](r是我们要枚举的位置,x是这个位置上的字母,y是枚举的另一字母)。

  用来更新最大值,这样的话我们枚举出来的字母就会出现两种情况,要么x比z多,要么z比x多。

  所以我们取一个最大值来更新答案,又因为这里的sum[x][l-1]-sum[y][l-1]是前面预处理出来的,所以每次在枚举到的位置取一最小值储存一下,并且记录是在什么时候更新的这个最小值。

  并且还要注意的是:

      当last[j]==(pos[j][now] || pos[now][j])时,如果减去的话就会直接把j这个字母消去,所以在后半段我们需要把这个多减去的1加上。

      后面一部分是加没错了,可是对于前面来说就是减去1,因为(sum[x][r]-sum[z][r])-(sum[x][l-1]-sum[z][l-1])嘛!

上代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#define INF 0x7fffffff
using namespace std;

const int Ms = 1011;
const int Ys = 26;
int n,ans,p,maxx,minn=INF;
char sr[Ms];
int s[Ys];

int max(int a,int b) 
{ return a > b ? a : b; } 

int dfs(int op,int ed,int now) {
    if(ed==n) return ans;
    s[now]++;
    maxx=0,minn=INF;
    for(int i=0; i<Ys; ++i) {
        if(s[i]==0) continue;
        if(s[i]>maxx) maxx=s[i];
        if(s[i]<minn) minn=s[i];
    }
    if(maxx-minn>ans) ans=maxx-minn;
    ed++;
    dfs(op,ed,sr[ed]-97);
}

int main() {
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    for(int i=0; i<n; ++i)
        cin>>sr[i];
    for(int i=0; i<n; ++i) {
        p=max(p,dfs(i,i,sr[i]-97));
        memset(s,0,sizeof(s));
        maxx=0,minn=INF,ans=0;
    }
    printf("%d",p);
    return 0;
}
60爆搜dfs

相关文章: