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 }
代码戳这里
posted @ 2019-08-22 09:13  小叽居biubiu  阅读(238)  评论(0编辑  收藏  举报