题目链接:cf 464A
给出一个长度为n,由前p个字母组成的任意子串都不是回文串的字符串。问是否存在字典序比它大的同样满足没有回文子串的字符串,若存在则输出字典序最小的那个
贪心,策略如下:
从后开始往前扫,修改字符串的值,因为本身给出的子串就已经满足了任意子串都不是回文串了,因此修改时只要保证当前位置的值与前一位和前面第二位不相等就能保证不会构成回文子串。找到某一位值字符修改可以满足条件之后,从该位开始后面的每一位从a开始枚举,找到最小的与前两位都不相同即可求得新的字符串
/******************************************************
* File Name: 464A.cpp
* Author: kojimai
* Creater Time:2014年09月09日 星期二 22时32分08秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 1005
char s[FFF];
char mm;
bool dfs(int now)
{
if(now==-1)
return false;
for(int i=1;i+s[now]<mm;i++)
{
if(now>0&&s[now]+i==s[now-1])
continue;
if(now>1&&s[now]+i==s[now-2])
continue;
s[now]+=i;
//当前位修改之后可以满足条件
return true;
}
//在前面位不变的情况下,当前位怎么修改都无法满足条件
if(!dfs(now-1))return false;
//前面的值修改之后,当前位从a开始枚举最小的符合条件的值
s[now]='a';
for(int i=0; i+s[now]<mm ;i++)
{
if(now>0&&s[now]+i==s[now-1])
continue;
if(now>1&&s[now]+i==s[now-2])
continue;
s[now]+=i;
return true;
}
return false;
}
int main()
{
int n,p;
scanf("%d%d",&n,&p);
scanf("%s",s);
mm='a'+p;
if(!dfs(n-1))
{
printf("NO\n");
}
else
printf("%s",s);
return 0;
}