HDU6103 Kirinriki 题解报告
【题目大意】
在给定的字符串序列中,找出两个不重的相同长度的子序列使得差异值不大于$m$,求满足条件的最长子序列的长度,其中两个长度为$n$的字符串$A,B$的差异值$dis=\sum_{i=1}^{n}|A_i-B_{n-i}|$。
【思路分析】
由于两个子序列长度相同,所以我们可以把它们看作是对称的,我们考虑枚举中间的对称轴,对称轴可能是序列中的一个位置,也可能是两个相邻位置之间的空隙。
一边枚举一边记录答案,最后枚举完所有的可能即可得出最大值。
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define g() getchar() 7 #define rg register 8 #define go(i,a,b) for(rg int i=a;i<=b;i++) 9 #define back(i,a,b) for(rg int i=a;i>=b;i--) 10 #define db double 11 #define ll long long 12 #define il inline 13 #define pf printf 14 using namespace std; 15 int fr(){ 16 int w=0,q=1; 17 char ch=g(); 18 while(ch<'0'||ch>'9'){ 19 if(ch=='-') q=-1; 20 ch=g(); 21 } 22 while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g(); 23 return w*q; 24 } 25 const int N=5002; 26 int T,m,len,ans; 27 char s[N]; 28 int main(){ 29 //freopen("","r",stdin); 30 //freopen("","w",stdout); 31 T=fr(); 32 while(T--){ 33 m=fr(); 34 scanf("%s",s); 35 len=strlen(s);ans=0; 36 go(i,1,len-1){//对称轴为序列中的一个位置 37 rg int l1=i-1,r1=l1; 38 rg int l2=i+1,r2=l2; 39 rg int sum=0; 40 while(l1>=0&&l2<len){ 41 sum+=abs(s[l1]-s[l2]); 42 while(sum>m) sum-=abs(s[r1--]-s[r2++]); 43 ans=max(ans,r1-l1+1); 44 l1--;l2++; 45 } 46 } 47 go(i,0,len-1){//对称轴为序列中两个相邻位置之间的空隙 48 rg int l1=i,r1=l1; 49 rg int l2=i+1,r2=l2; 50 rg int sum=0; 51 while(l1>=0&&l2<len){ 52 sum+=abs(s[l1]-s[l2]); 53 while(sum>m) sum-=abs(s[r1--]-s[r2++]); 54 ans=max(ans,r1-l1+1); 55 l1--;l2++; 56 } 57 } 58 pf("%d\n",ans); 59 } 60 return 0; 61 }