HDU-6103 Kirinriki - 2017 Multi-University Training Contest - Team 6(尺取)

题意:

给出一个字符串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;
}


继续加油~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值