HDU 6103Kirinriki

来源:互联网 发布:制作电子文档软件 编辑:程序博客网 时间:2024/06/05 17:53

【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=6103

题目意思

给出一串字符串,从中选出两个不重叠的字符串,使得两个字符串的距离和 <= m 的最长字符串长度,A,B 串中的字符距离计算为 disA,B=∑i=0n−1|Ai−Bn−1−i|

解题思路

看到这题时一开始想用的dp做后来,后来实在是想不出来动态转移方程(太菜没办法)后来发现直接用尺取就可以做了。从左右两边不断往中间收缩(从中间往两边扩也可以)。具体过程:i代表一个字符串的头从右边向左边移动,每次移动j都会从左边到右不断计算是否大于m了,大于了就把最靠边的不断减去直到加上后面的小于m,这样走一边就会找到以i为头的最长字符串(以i为头,但满足的字符串不一定要从i开始)。最后因为怕奇偶串所以要反过来再走遍。

代码部分

#include<bits/stdc++.h>using namespace std;#define ll long longint m,l;char s[50005];int solve(){    int ans=0;    for (int i=l; i>=1; i--)    {        int d=0,t=0,p=0;        for (int j=0; j<=i/2-1; j++)        {            d+=abs(s[1+j]-s[i-j]);              if (d>m)   ///当总和大于m,减去靠边的加上里面的;            {                d-=abs(s[1+p]-s[i-p]);                d-=abs(s[1+j]-s[i-j]);                p++;                t--;                j--;            }            else            {                t++;                ans=max(ans,t);            }        }    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int ans=0;        scanf("%d",&m);        scanf("%s",s+1);        l=strlen(s+1);        ans=max(ans,solve());        reverse(s+1,s+l+1);    ///反过来再跑遍        ans=max(ans,solve());        printf("%d\n",ans);    }    return 0;}
原创粉丝点击