• 51Nod 1701 最后的机会


    1701 最后的机会

    给定一字符串S,S非空,由小写字母组成,设v为S中元音字母的个数,c为辅音字母的个数。"a", "e", "i", "o", "u"为元音字母。其余为辅音字母。如果元音字母没有超过辅音字母的2倍,即v≤2c则称S是好的字符串。

    现在给定S,找出其中最长的好的子串的长度,以及个数。子串是由原串中连续的几个字符组成的。

    样例解释:

    在样例一中,最长的子串是他的自身“abo”。其它好的子串是“b”,“ab”,“bo”,但是都不是最长的。

    在样例二中,最长的子串是“eis”。其它好的子串是“s”,“is”,但是都不是最长的。

    输入

    单组测试数据。
    共一行字符串S(S非空且长度不大于2*10^5),由小写字母组成。其中"a", "e", "i", "o", "u"为元音字母。其余为辅音字母。

    输出

    输出两个整数,以空格隔开,分别表示最长的好的子串的长度和以及个数。如果没有好的子串则输出 "No solution" (没有引号)。
    
    两个子串出现的位置不一样则称为是不同的子串。如果同一个子串在不同位置出了多次,则要统计多次。

    输入样例

    样例一
    abo
    样例二
    oeis

    输出样例

    输出一
    3 1
    输出二
    3 1

    分析

    对于符合的任意一段子序列(长度为len),假设其元音字符的个数为sum, 则依题意有sum<=2*(len-sum);

    假如求出了元音字符数量的前缀和sum[]. 具体一点,假设这个子序列的左右下标为 i 和 j ,则有:

    sum[j]-sum[i-1]<=2*((j-i+1)-(sum[j]-sum[i-1])) , 移项得 3*sum[j]-2*j<=3*sum[i-1]-2*(i-1), 想到可以记录一个

    数组存储3*sum[i]-2*i的值。我们要求的最大长度即是满足上式的距离最远的i和j,只需再开一个数组rmin

    (右边的最小值),用单调的思想处理一下,枚举i然后二分查找j,更新最大长度。。。

    代码如下:

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    bool ok(char c)
    {
        return c=='a'||c=='e'||c=='i'||c=='o'||c=='u';
    }
    char s[200005];
    int ans1,ans2;
    int sum[200005];
    int T[200005];
    int rmin[200005];
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%s",s);
    
        int n=strlen(s);
        for(int i=1;i<=n;i++)
            if(ok(s[i-1]))sum[i]=sum[i-1]+1;
            else sum[i]=sum[i-1];
    
        for(int i=1;i<=n;i++)
            T[i]=3*sum[i]-2*i;
    
        int tmp=0x3f3f3f3f;
        for(int i=n;i>=1;i--)
        {
            tmp=min(tmp,T[i]);
            rmin[i]=tmp;
        }
    
        for(int i=1;i<=n;i++)
        {
            int v=3*sum[i-1]-2*(i-1);
            int j=upper_bound(rmin,rmin+1+n,v)-rmin; j--;
            if(i<=j){ans1=max(ans1,j-i+1);}
        }
    
        for(int i=1,j=i+ans1-1;j<=n;i++,j++)
        {
            if(3*sum[j]-3*sum[i-1]<=2*(j-i+1))ans2++;
        }
    
        if(ans1==0){printf("No solution
    ");}
        else printf("%d %d
    ",ans1,ans2);
    
        return 0;
    }
    
  • 相关阅读:
    电话聊天狂人
    PAT 1080. MOOC期终成绩
    PAT 1079. 延迟的回文数
    [转载]matlab 中序列求极值的方法
    [转载][转]Matlab-寻找峰值函数
    [转载]Kirchhoff Migration Impulse Response
    Envelope Extraction Using the Analytic Signal
    [转载]地震动的挑选
    C笔记
    Git常用有用命令
  • 原文地址:https://www.cnblogs.com/linruier/p/10344717.html
Copyright © 2020-2023  润新知