这里读了一篇博客:
关键是找到规律然后dp,这是dp吧,好像是的...
首先我们记录每个字符的位置序列到一个vector中
接下来就是规律:
比如这个a.....a这个序列,要把前面那个a移动到与后面那个a相邻,最小的次数是不是下标相减再减1呢?没错就是这样
我们第一步先把同字符移动到相邻需要的步数记录下来,接着更新大的。
然后来考虑一个a...a...a...a的例子,这样把a移动到相邻最少多少步呢?可以想象,中间的已经求出来了,我们只要把两边的a缩到中间就行,那其实是下标相减减1再减去中间相同字符的个数。
这样我们就求出了使某一个字符在一定数量上相邻所花费的最小交换次数,接着选出连续最大的区间,交换次数小于要求的就是我们要的
代码如下所示:
#include <bits/stdc++.h>
using namespace std;
int m;
string str;
int maxi(vector<int>& x){
int n=x.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for (int i = 0; i < n-1; ++i) {
dp[i][i+1]=x[i+1]-x[i]+1;
}
for (int k = 2; k < n; ++k) {
for (int i = 0; i < n-k; ++i) {
int left=i,right=i+k;
dp[left][right]=dp[left+1][right-1]+(x[right]-x[left]-1)-(right-left-1);
}
}
int res=0;
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
if(dp[i][j]<=m&&(j-i+1)>res){
res=j-i+1;
}
}
}
return res;
}
int main() {
cin>>str>>m;
vector<vector<int>> a(26);
for (int i = 0; i < str.size(); ++i) {
a[str[i]-'a'].push_back(i);
}
int res=0;
for (int i = 0; i < 26; ++i) {
int num=maxi(a[i]);
if (num>res) res=num;
}
cout<<res<<endl;
return 0;
}