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