nyoj LYQの字符串(尺取法)

来源:互联网 发布:网络语鸡肋是什么意思 编辑:程序博客网 时间:2024/05/14 07:47

LYQの字符串

题目描述
一个字符串如果其所有长度为奇数的子串都是回文串那么就称这个字符串是奇回文串。

给你一个长度为N的字符串,假如让你最多可以修改k个字符,你的目标是求出最长的奇回文子串。がんばって

输入
第一行一个正整数K,如上所述。

第二行是一个字符串S。

1≤K≤N≤106。

S只包含小写字母。

输出
输出奇回文字串的最大长度。
样例输入
3
abbc
1
ab
1
abcdef
1
accca
3
abcd
样例输出
4
2
3
5
4
题目链接:LYQの字符串

思路:
根据题意的描述,如果这个字符串是奇回文串,那么这个字串中对于任何的i,都符合s[i]=s[i+2].所以奇数位上的字符都相同,偶数位同理。

如果有一个子串两个条件都满足那么这个子串就可以当做答案之一了,但是可以修改k个字符,因此答案还可以贪心增长。

我们单独考虑奇偶位上的字符,最优策略当然是保留出现次数最多的那个,我们可以用两点法(尺取?),每一步都找两种情况中出现频率最多的字符,这个可以用26*2的数组来统计,遍历一遍找出最优解即可。

代码:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn=1e6+10;char str[maxn];int vis[26][2];int k;int main(){    while(~scanf("%d",&k))    {        memset(vis,0,sizeof(vis));        scanf("%s",str);        int len=strlen(str);        int j=0,ans=0;//j表示区间结尾        for(int i=0; i<len; ++i)//i表示区间开头        {            if(i>0)                --vis[str[i-1]-'a'][(i-1)&1];            int max_odd=0,max_even=0;            for(int k=0; k<26; ++k)            {                max_odd=max(max_odd,vis[k][1]);                max_even=max(max_even,vis[k][0]);            }            int num=j-i-max_odd-max_even;            while(num<=k&&j<len)            {                ++vis[str[j]-'a'][j&1];                if(j&1)                    max_odd=max(max_odd,vis[str[j]-'a'][j&1]);                else                    max_even=max(max_even,vis[str[j]-'a'][j&1]);                num=j-i+1-max_odd-max_even;                if(num<=k&&j-i+1>ans)                    ans=j-i+1;                ++j;            }        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击