其他分享
首页 > 其他分享> > ok 字符串

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 }

 

标签:子串,字符,ok,延伸,样例,修改,字符串
来源: https://www.cnblogs.com/rabbit1103/p/14798690.html