题意:
给你一个区间,定义了两个子区间的距离不能大于m ,问满足这样距离的子区间最大长度。
区间距离dis(x,y)= abs(x1-yn)+abs(x2-yn-1).......;
题解:
2s 5000长度,总长度20000.
n^2 勉强能过。
很明显可以看出来所有满足题意的两点满足回文性质, 所以枚举每个子串的的中点, 然后依次向两边扩散,
然后枚举的中点即可能是一个点,也可能是两个点的中间,所以推两边即可。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5005;
char s[maxn];
int T,m,ed;
int Abs(int x){
if(x<0)return -x;
return x;
}
int solve(char *s){
int ans=0;
for(int i=0;i<ed;++i){
int pre=i,sub=i+1,ret=0,cnt=0;
int pt=i,st=i+1;
while(pre>=0&&sub<ed){
ret+=Abs(s[pre]-s[sub]);
if(ret>m){
ret-=Abs(s[pre]-s[sub]);
if(st!=sub){
ret-=Abs(s[st]-s[pt]);
cnt--,pre++,sub--;
}
pt--;st++;
}else{
cnt++;
ans=max(ans,cnt);
}pre--,sub++;
}
}
return ans;
}
int solve1(char *s){
int ans=0;
for(int i=0;i<ed;++i){
int pre=i-1,sub=i+1,ret=0,cnt=0;
int pt=i-1,st=i+1;
while(pre>=0&&sub<ed){
ret+=Abs(s[pre]-s[sub]);
if(ret>m){
ret-=Abs(s[pre]-s[sub]);
if(st!=sub){
ret-=Abs(s[st]-s[pt]);
cnt--,pre++,sub--;
}
pt--;st++;
}else{
cnt++;
ans=max(ans,cnt);
}pre--,sub++;
}
}
return ans;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&m);
scanf("%s",s);
ed=strlen(s);
int t=solve(s);
t=max(t,solve1(s));
printf("%d\n",t);
}
return 0;
}