题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6103
很好的题,很容易看出用尺取法的思想,但是我实现不了代码。
借鉴(抄下)这里的代码才明白诀窍:https://blog.youkuaiyun.com/qq_36306833/article/details/77073444
首先要保持已有的长度不变,因为更短的可以不考虑了,所以没必要在把头部减去的时候还把长度剪掉,只要看有没有更长的匹配即可。
代码开始部分把字符串翻转了一下,不翻转不是不能做,但是思考就会绕圈,翻转可以减轻很多思维上的负担。
下面j<(len-i)/2是因为2+2j+i<=len,那么j<=(len-i)/2-1即j<(len-i)/2。
i<len-1,因为i是偏移量,那么相当于最起码有s1[0]和s1[1]进行匹配,保证的是最少能匹配长度1的串。
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=2e4+5;
char s1[maxn],s2[maxn];
int main(void){
//freopen("in.txt","r",stdin);
int t,m;
scanf("%d",&t);
while (t--){
scanf("%d %s",&m,s1);
int ans=0,len=strlen(s1);
for(int i=0;i<len;i++)s2[i]=s1[len-i-1];
for(int i=0;i<len-1;i++){//偏移量
int res=0,sum=0;
for(int j=0;j<(len-i)/2;j++){
sum+=abs(s1[j]-s2[j+i]);
if(sum>m){
sum-=abs(s1[j-res]-s2[j+i-res]);
continue;
}
res++;
}
ans=max(ans,res);
}
for(int i=0;i<len-1;i++){//偏移量
int res=0,sum=0;
for(int j=0;j<(len-i)/2;j++){
sum+=abs(s2[j]-s1[j+i]);
if(sum>m){
sum-=abs(s2[j-res]-s1[j+i-res]);
continue;
}
res++;
}
ans=max(ans,res);
}
printf("%d\n",ans);
}
return 0;
}