zoukankan      html  css  js  c++  java
  • 【BZOJ2213】[Poi2011]Difference DP

    【BZOJ2213】[Poi2011]Difference

    Description

    A word consisting of lower-case letters of the English alphabet ('a'-'z') is given. We would like to choose a non-empty contiguous (i.e. one-piece) fragment of the word so as to maximise the difference in the number of occurrences of the most and the least frequent letter in the fragment. We are assuming that the least frequent letter has to occur at least once in the resulting fragment. In particular, should the fragment contain occurrences of only one letter, then the most and the least frequent letter in it coincide.

    已知一个长度为n的由小写字母组成的字符串,求其中连续的一段,满足该段中出现最多的字母出现的个数减去该段中出现最少的字母出现的个数最大。求这个个数。

    Input

    The first line of the standard input holds one integer (1<=N<=1000000)() that denotes the length of the word. The second line holds a word consisting of lower-case letters of the English alphabet.

    第一行,n
    第二行,该字符串
    1<=n<=1000000

    Output

    The first and only line of the standard output is to hold a single integer, equal to the maximum difference in the number of occurrences of the most and the least frequent letter that is attained in some non-empty contiguous fragment of the input word.

    一行,表示结果

    Sample Input

    10
    aabbaaabab

    Sample Output

    3
    Explanation of the example: The fragment that attains the difference of 3 in the number of occurrences of a and b is aaaba.

    题解:我承认我做的可能有点麻烦~

    先枚举出现次数最少的字符,然后设f[i][0]表示以i结束的最长一段区间使得(位置为i的字符出现次数-最少的字符出现的次数)最大,不强制要求区间中必须出现过次数最少的字符,f[i][1]表示强制区间中必须出现过次数最少的字符,然后DP搞一

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=1000010;
    int n,ans;
    int pre[maxn],s[maxn],f[maxn][2],head[30];
    char str[maxn];
    void calc(int cn)
    {
    	int i;
    	for(i=1;i<=n;i++)	s[i]=s[i-1]+(str[i]=='a'+cn);
    	if(!s[n])	return ;
    	f[0][0]=0,f[0][1]=-1<<30;
    	for(i=1;i<=n;i++)
    	{
    		if(str[i]=='a'+cn)	continue;
    		f[i][0]=max(f[pre[i]][0]+1-s[i]+s[pre[i]],1);
    		f[i][1]=(s[i]>s[pre[i]])?max(f[pre[i]][0]+1-s[i]+s[pre[i]],0):(f[pre[i]][1]+1);
    		ans=max(ans,f[i][1]);
    		if(s[n]-s[i])	ans=max(ans,f[i][0]-1);
    	}
    }
    int main()
    {
    	scanf("%d%s",&n,str+1);
    	int i;
    	for(i=1;i<=n;i++)	pre[i]=head[str[i]-'a'],head[str[i]-'a']=i;
    	for(i=0;i<26;i++)	calc(i);
    	printf("%d",ans);
    	return 0;
    }
     
  • 相关阅读:
    Linux每日一题——(2)vi文本编辑器
    Oracle每日一题——(1) 启动/停止监听
    Linux每日一题——(1)创建和删除用户
    Oracle实践:00600[4193]错误导致服务频繁宕掉问题
    在AX中生成二维码
    AX向在线用户发送消息
    TimeNow()获取时间与当前时间不符
    Changecompany中使用Box,Info等客户端方法后出错
    AX4.0删除引用
    poj1010解题报告
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7044252.html
Copyright © 2011-2022 走看看