zoukankan      html  css  js  c++  java
  • ok 字符串

    问题描述

    商场中展示了这么多玩具,乐乐爱不释手。现在游戏环节开始,只要你能解决一个问题,就能够挑选一件精美的玩具。此时,乐乐需要你们这帮“牛娃”的帮助,请你帮助乐乐解决这个问题。 
    现在给你一个长度为 n 的字符串,该字符串只包含字符‘o’和‘k’。你最多可以修改 t 个字符(将字符‘o’改为字符‘k’或将字符‘k’改为字符‘o’),使得某一段连续相同的字符个数是最多的。
    例如:‘ooooo’或‘kkkkk’像这样的连续相同字符都可以。 
    请你经过不多于t次地合理修改,帮助乐乐求出字符串某一段连续相同的字符最多个数。

    输入格式

    第一行输入整数 n 和 t,分别表示字符串的总长度和最多可以修改的字符数。 
    第二行输入一行字符串,仅包含字符‘o’或‘k’。

    输出格式

    输出一个整数,表示经过不多于 t 次地合理修改,字符串某一段连续相同的字符最多个数。

    样例输入

    【样例1】

    4 2

    okko

    【样例2】

    8 3

    ookookoo

    样例输出

    【样例1】

    4

    【样例2】

    8

    提示

    样例一:通过 2 次修改后,可以获得字符串‘oooo’或‘kkkk’,所以连续的字符个数是 4。 
    样例二:虽然 t 是 3,但只需通过 2 次修改后,可以获得字符串‘oooooooo’,连续的字符个数是 8。

    数据范围

    对于80%的数据,保证 1≤n≤10000,0≤t≤n。 
    对于另外20%的数据,保证 n≤1000000, 0≤t≤10000,并保证字符‘o’的总个数≤10000
    或字符‘k’的总个数≤10000。 

    题解

    将问题简化为以下两个小问题:

    1、将字符‘k’改为字符‘o’,使得某一段连续的‘o’最多;

    2、将字符‘o’改为字符‘k’,使得某一段连续的‘k’最多。

     

    先解决第一个问题,即最多把t个字符从‘k’改为‘o’,使某一段连续的‘o’最多。

    显然最优解一定是改掉t个字符

    要找出最长的连续相同‘o’的子串,在不修改任何字符的情况下,显然要让子串尽量延伸,即,若i的前面或j的后面还有‘o’,那么这样的子串一定不是最优解,因为还有延伸的空间

    当子串的前后都是‘k’时,子串无法再延伸,这时就可以修改字符使子串继续延伸

    例如,对于字符串oookoookkkkooookoko,有4次修改机会

    我们从第一个字符开始,I=j=1,此时子串无法向前(i-1)延伸,但是可以向后(j+1)延伸,直到遇到一个‘k’(此时j=3),将其改成‘o’后继续延伸(j=4),直到遇到一个‘k’时已经修改了t个字符(此时j=10),子串无法再延伸,此时可以记录子串的长度,为10

    接下来将子串的头缩短,即将i向后移

    显然,i无论停留在2或者3都没有意义,因为这样的i可以向前延伸到1使子串更长

    而当i越过一个‘k’,停留在5时,就到了转折点

    此时原本被改为‘o’的‘k’已经在子串之外了,我们就可以收回这次修改,用于j的下一个字符,这样j就可以再向右扩展到15,此时子串长度为11。以此类推,我们可以一直移动、延伸子串直到j指向整个字符串的最后一个字符,我们可以在移动的过程中求出最大的连续‘o’个数

    于是我们得到以下算法:

    令i指向当前最长的连续‘o’的子串的第一个字符,j指向最后一个字符

    从第一个字符开始,初始时连续‘o’的子串长度为一,i和j都指向第一个字符

    若j的下一个字符是‘o’,显然当前子串可以更长,将j向后移动一个字符

    若j的下一个字符是‘k’,而此时修改的字符数不超过t,则将下一个字符改成‘o’,子串可以再变长;若此时修改的字符数已经达到t,则将i往后移,直到遇到第一个‘k’,令i指向第一个‘k’的下一个字符,则可以收回一次修改字符的机会,将其用于j指向的字符

    对于修改‘o’同理,综合两个问题的结果取最大值即为本题的答案

     1 #include <cstdio>
     2 int n,t,ans;
     3 char s[1000005];
     4 void deal(char ch)
     5 {
     6     int i,j;
     7     i=j=1;
     8     if (s[1]!=ch) t--;
     9     while (j<n)
    10     {
    11         for (;j<n && s[j+1]==ch;j++);
    12         if (j-i+1>ans) ans=j-i+1;
    13         if (j==n)
    14         {    
    15             break;
    16         }
    17         if (t) 
    18         {
    19             t--;
    20             j++;
    21             if (j-i+1>ans) ans=j-i+1;
    22             continue;
    23         }
    24         for (;i<j && s[i]==ch;i++);
    25         i++;  j++;
    26     }
    27     return;
    28 }
    29 int main()
    30 {
    31     int i,j,tt;
    32     scanf("%d%d",&n,&tt);
    33     scanf("%s",s+1);
    34     t=tt;
    35     deal('o');
    36     t=tt;
    37     deal('k');
    38     printf("%d",ans);
    39     return 0;
    40 }
  • 相关阅读:
    rabbitmq在centos7下安装
    跨域问题
    11生成器相关及推导式(附内置函数分析图url)
    10函数名的应用,闭包,和迭代器
    09函数的动态传参及global和nonlocal关键字
    08函数简介
    07基本的文件操作
    06set集合和深浅拷贝(包括前面的一些知识点补充)
    05判断和编码/解码
    04基本数据类型(字典)
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/14798690.html
Copyright © 2011-2022 走看看