2017 Multi-University Training Contest

来源:互联网 发布:汉字拼音发音软件 编辑:程序博客网 时间:2024/06/05 07:48

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


题目链接:
HDU 6103 Kirinriki


题目大意:
给一个字符串s,和一个值m.
定义disA,B=i=0n1|AiBn1i| .
在s串中找出最长的AB子串使得dis{A,B}m


解题思路:

比赛的时候这道题给的数据是|S|20000。 就在想O(nlogn)的复杂度, 不敢写O(n2)的, 最后实在没办法写了O(n2)的, 没想到官方题解就是让用O(n2)做。。。

首先可以枚举一个对称点, 然后用尺取法往外扩张,考虑两种情况, 中间的留一个字母和中间不留字母。

代码:

/********************************************** *Author*        :ZZZZone *reated Time*  : 2017/8/11 13:47:16 *ended  Time*  : 2017/8/11 14:07:47*********************************************/#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>#include <stack>using namespace std;typedef pair<int, int> PII;typedef long long LL;typedef unsigned long long ULL;const int MaxN = 5e3;int T, m, ans, len;char s[MaxN + 5];void check(int p){    int r = p;     int tot = 0;    for(int i = p; i >= 0; i--){        int tmp = 2 * p + 1;        if(tmp - i >= len) break;        tot += abs(s[i] - s[tmp - i]);        while(tot > m && r >= i){            tot -= abs(s[r] - s[tmp - r]);            r--;        }        ans = max(ans, r - i + 1);    }    tot = 0, r = p - 1;    for(int i = p - 1; i >= 0; i--){        int tmp = 2 * p;        if(tmp - i >= len) break;        tot += abs(s[i] - s[tmp - i]);        while(tot > m && r >= i){            tot -= abs(s[r] - s[tmp - r]);            r--;        }        ans = max(ans, r - i + 1);    }}int main(){    scanf("%d", &T);    while(T--){        scanf("%d", &m);        scanf("%s", s);        ans = 0; len = strlen(s);        for(int i = 0; i < len; i++) check(i);        printf("%d\n", ans);    }    return 0;}
原创粉丝点击