题意:给出初始串长度为n,包含前p个字符的合法string,n<=1e3,p<=26 合法串为:不包含长度>=2的回文子串,求下一个字典序大于初始串的合法的子串?
无长度>=2的回文子串 :任意连续两个不能相同a[i]!=a[i-1]
若以i为中心无长度为3的回文子串 则也没有长度l>3的回文子串 所以a[i-1]!=a[i+1]
为了构造出下一个合法排列:先找到第一个能往上变化的a[i],若p>=3,之后按照上面两个合法的条件上生成string即可
初始串为合法的,所以p=1||p==2的初始串长度只能为1或者2,也能按照上面生成.
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> ii;
const int inf=1e9;
const int N=2e5+20;
char s[N];
int n,p,x;
int a[N];
void print()
{
for(int i=0;i<n;i++)
printf("%c",a[i]+'a');
printf("\n");
}
int main()
{
while(cin>>n>>p)
{
bool flag=false;
scanf("%s",s);
for(int i=0;i<n;i++)
a[i]=s[i]-'a';
int po,val;
for(int i=n-1;i>=0;i--)//找到第一个能增大的字符的位置
{
for(int j=a[i]+1;j<p;j++)
{
if((i-1<0||a[i-1]!=j)&&(i-2<0||a[i-2]!=j))
{
val=j;
po=i;
flag=true;
break;
}
}
if(flag)
break;
}
if(flag==false)
{
puts("NO");
continue;
}
a[po]=val;
for(int i=po+1;i<n;i++)
{
for(int k=0;k<p;k++)
{
if((i-1<0||k!=a[i-1])&&(i-2<0||k!=a[i-2]))
{
a[i]=k;
flag=true;
break;
}
}
}
print();
}
return 0;
}