HDU-6103

  1. Kirinriki

    Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1204 Accepted Submission(s): 475

    Problem Description
    We define the distance of two strings A and B with same length n is
    disA,B=∑i=0n−1|Ai−Bn−1−i|
    The difference between the two characters is defined as the difference in ASCII.
    You should find the maximum length of two non-overlapping substrings in given string S, and the distance between them are less then or equal to m.

    Input
    The first line of the input gives the number of test cases T; T test cases follow.
    Each case begins with one line with one integers m : the limit distance of substring.
    Then a string S follow.

    Limits
    T≤100
    0≤m≤5000
    Each character in the string is lowercase letter, 2≤|S|≤5000
    ∑|S|≤20000

    Output
    For each test case output one interge denotes the answer : the maximum length of the substring.

    Sample Input
    1
    5
    abcdefedcb

    Sample Output
    5

    Hint
    [0, 4] abcde
    [5, 9] fedcb
    The distance between them is abs(‘a’ - ‘b’) + abs(‘b’ - ‘c’) + abs(‘c’ - ‘d’) + abs(‘d’ - ‘e’) + abs(‘e’ - ‘f’) = 5

    Source
    2017 Multi-University Training Contest - Team 6

    本题题意:
  2. 就是让你找出两个子串A,B满足 disA,B=i=0n1|AiBn1i| <=m 的最大区间长度
  3. 由于有一百组样例 每个样例字符串的长度是5000 所以暴力的话肯定超时


我们应该考虑如何才能找到区间最大长度 满足条件的

由于若A,B满足条件那么A,B的子串长度就必然满足条件   由于单调性原则   长到一定限度就不满足

而低于m又可以增加长度   考虑尺取法

如何尺取?

我们可以枚举左串的起点 和 右串的终点 因为这样必然最大子串长度在这个枚举之中

然后最每一次枚举

我们用尺取法尺取区间长度 如果此时dis小于m那么就可以向中间延伸 如果大于m那么就不断地把两边去掉

复杂度O(n^2)


code:

#include<bits/stdc++.h>
using namespace std;
int m;//25000000
string ll;
int solve(int l,int r)
{
	int st=0,ed = 0,dis=0;
	int ma=0;
	while(l+ed<r-ed){
		int t = abs(ll[l+ed]-ll[r-ed]);
		if(dis+t<=m){
			dis+=t;
			ed++;
			ma = max(ma,ed-st);
		}
		else
		{
			dis-=abs(ll[l+st]-ll[r-st]);
			st++;
		}
	}
	return ma;
}
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&m);
		getchar();
		getline(cin,ll);
		int ans = 0;
		int len = ll.length();
		for(int i=1;i<len;i++)
			ans = max(ans,solve(0,i));
		for(int i=0;i<len-1;i++)
			ans = max(ans,solve(i,len-1));
		printf("%d\n", ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值