题意:给了一个字符串,一组数代表字符间隔a1,a2...ai,要求必须且只能交换一次两个间隔为ai的字符,求形成新的字典序最小的字符串
分析:贪心,从前往后找第一个字符比后面大的(意味着可以交换越靠前的被替换字典序就越小),然后这个位置固定,看之后有没有比它还要小的可以替换它。如果没有这样的字符就说明当前字典序已经最小,看一下是否有给定距离的相同的字母(这样可以保证至少字典序不变),没有的话就交换最后的字符和它前面距离最小的字符
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
char s[maxn];
int a[55];
int main()
{
while(~scanf("%s",s))
{
int len = strlen(s);
int n,minx = -1,mini;
bool flag = false;
cin>>n;
for(int i = 1; i <= n; i++)
cin>>a[i];
sort(a + 1,a + n + 1);
for(int i = 0; i < len; i++)
{
for(int j = 1; j <= n; j++)
{
if(i + a[j] >= len)break;
if(s[i + a[j]] < s[i])
{
flag = true;
break;
}
}
if(flag)
{
int ans = i + a[1];
for(int j = 2; j <= len; j++)
{
if(i + a[j] >= len)break;
if(s[i + a[j]] <= s[ans])
{
ans = i + a[j];
}
}
swap(s[i],s[ans]);
printf("%s\n",s);
return 0;
}
}
for(int i = 0; i < len; i++)
for(int j = 1; j <= n; j++)
{
if(i + a[j] >= len)break;
if(s[i] == s[i + a[j]])
{
printf("%s\n",s);
return 0;
}
}
swap(s[len - 1],s[len - 1 - a[1]]);
printf("%s\n",s);
}
return 0;
}