动规题目:字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?参考博客
#include <iostream>
#include <string.h>
#include <algorithm>
#define N 26
using namespace std;
//返回将i和j中所有该字母移动到一起所需最少步数
int dp(int i,int j,int a[]){
if(i == j) return 0;
else if(i+1 == j) return a[j]-a[i]-1;
//当一个字母出现多次且不连续时,应从两侧往中间移,这样才能保证移动次数最少。找规律得到状态转移方程
else return dp(i+1,j-1,a)+a[j]-a[i]-(j-i);
}
int main(){
string str;
int num;
cin >> str >> num;
int length = str.length();
int a[length][N];
int b[N]; //存放各字母在满足约束的情况下最大的连续数
int m[length]; //各字母出现的位置
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(m,0,sizeof(m));
//lengthx26的矩阵,出现字母的地方都置1
for(int i=0;i<length;i++)
for(int j=0;j<N;j++)
a[i][str[i]-'a'] = 1;
for(int j=0;j<N;j++){
int k=0; //该字母出现的总次数
for(int i=0;i<length;i++)
if(a[i][j] == 1)
m[k++] = i;
if(k == 1) b[j] = 1;
else if(!k) b[j] = 0;
else{
int temp=-1;
//将字符串中第i到第ii个该字母移动到一起是否可行
for(int i=0;i<k;i++)
for(int ii=i+1;ii<k;ii++)
if(dp(i,ii,m)<=num && ii-i+1>temp)
temp = (ii-i)+1;
b[j] = temp;
}
}
sort(b,b+N);
cout << b[N-1] << endl;
return 0;
}