HDU-6103 Kirinriki

来源:互联网 发布:依阿华级战列舰 知乎 编辑:程序博客网 时间:2024/06/05 20:49
题意:

给出一个字符串s,找其两个长度相同且不重叠的子串,满足两个子串相对应的每位ASCLL码差值绝对值之和不大于m,求满足条件的最长子串长度。

思路:

由于单个数据长度才5000,所以可以想一个枚举的思路。

可以将主串分成前后两个等长的子串,第二个串进行一次反向,然后我们可以将两个串上下对齐,然后进行下述操作:上串保持不动,下串一直往后挪,,当上串的相对位置比下串少1个时,下串末尾移至上传末尾(不正好是原串中这个上串的下一个位置的字符嘛),在每一次挪动中,就进行第二个串长度的一次尺取。最后再将串反向进行上述操作一次,就将全部的可能都考虑到了。假如s串为abcdefghi,操作如下:


代码:

#include <bits/stdc++.h>using namespace std;const int maxn = 5005;char s[maxn], s1[maxn], s2[maxn];int m, t, ans, mlen;void work(){int len1, len2;len1 = len2 = mlen/2;    if(mlen & 1) ++len2;strcpy(s1, s); s1[len1] = '\0';strcpy(s2, s+len1); s2[len2] = '\0';reverse(s2, s2+len2);    for(int k = 0; k < len1; ++k)    {    int q1, h1, q2, h2;        int now = 0;q1 = k, q2 = 0;        h1 = k, h2 = 0;        while(h1 < len1)        {            now += abs(s1[h1]-s2[h2]);            while(now > m)            {                now -= abs(s1[q1]-s2[q2]);                ++q1, ++q2;            }            ans = max(h1-q1+1, ans);            ++h1, ++h2;        }        if(len1-k == len2-1)        {            s1[len1] = s2[len2-1];            ++len1, --len2;            s1[len1] = s2[len2] = '\0';        }        if(ans >= len2) break;    }}int main(){    scanf("%d", &t);    while(t--)    {        ans = 0;        scanf("%d %s", &m, s);        mlen = strlen(s);        work();        reverse(s, s+mlen);        work();        printf("%d\n", ans);    }    return 0;}


继续加油~