【枚举】【尺取法】hdu6103 Kirinriki

两个等长字符串A,B的距离被定义为

给你一个字符串,问你对于所有长度相等的不相交子串对,其距离不超过m的前提下,最长的长度是多少。

枚举对称轴,两侧先贪心地扩展到最长,超过m之后,再缩短靠近对称轴的端点,如此反复进行,每次更新答案的时候,都用的是当前“近对称轴端点”固定时的最长值。

复杂度O(n^2)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int Abs(int x){
	return x<0 ? (-x) : x;
}
int T,m,n;
char a[5005];
int main(){
	scanf("%d",&T);
	for(;T;--T){
		int ans=0;
		scanf("%d%s",&m,a+1);
		n=strlen(a+1);
		for(int i=1;i<n;++i){
			if(i==6){
				i=6;
			}
			int sum=0;
			int p1=i,p2=i+1,q1=i,q2=i+1;
			while(p1>=1 && p2<=n){
				while(sum<=m && p1>=1 && p2<=n){
					sum+=Abs(a[p1]-a[p2]);
					if(sum<=m){
						ans=max(ans,q1-p1+1);
					}
					--p1;
					++p2;
				}
				while(sum>m){
					sum-=Abs(a[q1]-a[q2]);
					--q1;
					++q2;
					if(sum<=m){
						ans=max(ans,q1-p1);
					}
				}
			}
		}
		for(int i=2;i<n;++i){
			int sum=0;
			int p1=i-1,p2=i+1,q1=i-1,q2=i+1;
			while(p1>=1 && p2<=n){
				while(sum<=m && p1>=1 && p2<=n){
					sum+=Abs(a[p1]-a[p2]);
					if(sum<=m){
						ans=max(ans,q1-p1+1);
					}
					--p1;
					++p2;
				}
				while(sum>m){
					sum-=Abs(a[q1]-a[q2]);
					--q1;
					++q2;
					if(sum<=m){
						ans=max(ans,q1-p1);
					}
				}
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
时间: 2024-10-06 13:33:17

【枚举】【尺取法】hdu6103 Kirinriki的相关文章

HDU 6103 Kirinriki 枚举长度 尺取法

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6103 题目描述: 定义两个相同长度的字符串的值为首尾开始字符串的ASCII相减, 求一个字符串中任取两个相同长度的不重叠的值不超过m的最大长度 解题思路: 求连续区间不超过某一个上限或者不低于某个下限的应该用尺取法 ,复杂度为O(n),  本题n是5000所以O(n^2)可行, 枚举前缀和后缀(通过枚举前缀, 再将字符串翻转枚举前缀进行), 再进行尺取 代码:  代码中有注释 #include <

HDU 6103 Kirinriki(尺取法)

http://acm.hdu.edu.cn/showproblem.php?pid=6103 题意: 给出一个字符串,在其中找两串互不重叠的子串,计算它们之间的dis值,要求dis值小于等于m,求能选的子串的最大长度. 思路: 由于这两个子串是互不重叠的,那么这两个子串之间的间隔可以是奇数也可以是偶数,针对这两种情况我们枚举中心点,然后尺取法处理,具体看代码就懂了. 1 #include<iostream> 2 #include<algorithm> 3 #include<c

hdu6103[尺取法] 2017多校6

/*hdu6103[尺取法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, m; char str[20005]; void solve() { int ans = 0; int n = strlen(str); for (int i = 0; i < n; i++) { int l = 0, r = 0, p1 = i, p2 = i + 1, cost = 0; while (p1 - r >= 0

luogu 1712 区间(线段树+尺取法)

题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭区间,然后线段树的每一个节点表示一个半开半闭区间. 接着我们注意到需要求最小的花费,且这个花费只与选择的区间集合中的最大长度和最小长度有关. 这意味着如果最大长度和最小长度一定,我们显然是需要把中间长度的区间尽量的选择进去使答案不会变的更劣. 不妨把区间按长度排序,枚举每个最小长度区间,然后最大区间

poj 3320 Jessica&#39;s Reading Problem(尺取法+map/hash)

题目:http://poj.org/problem?id=3320 题意:给定N个元素的数组,找出最短的一段区间使得区间里面的元素种类等于整个数组的元素种类. 分析:暴力枚举区间的起点x,然后找到最小的y,使得区间[x,y]满足条件,x向有移位后变成x',现在的y'肯定不至于在y的左边.存状态的话map和hash都可以. map代码: #include <iostream> #include <set> #include <map> #include <cstdi

BestCoder Round #86 二,三题题解(尺取法)

第一题太水,跳过了. NanoApe Loves Sequence题目描述:退役狗 NanoApe 滚回去学文化课啦! 在数学课上,NanoApe 心痒痒又玩起了数列.他在纸上随便写了一个长度为 nnn 的数列,他又根据心情随便删了一个数,这样他得到了一个新的数列,然后他计算出了所有相邻两数的差的绝对值的最大值. 他当然知道这个最大值会随着他删了的数改变而改变,所以他想知道假如全部数被删除的概率是相等的话,差的绝对值的最大值的期望是多少. 输入描述 第一行为一个正整数 T,表示数据组数. 每组数

HDU 5358 First One 数学+尺取法

多校的题,摆明了数学题,但是没想出来,蠢爆了,之前算了半天的s[i][j]的和,其实是积.其实比赛的时候我连log(s[i][j])+1是s[i][j]的位数都没看出来,说出来都丢人. 知道了这个之后,就枚举二进制数的每一位,因为元素都是非负数,所以sum数组是非降的,这里用到了尺取法,之前也是听说过,应该是做过吧,不太记得了. 因为[2k-1,2k)的位数是k,枚举时,固定左端点,在sum数组找到最小的大于等于2k-1,最大的小于2k的点,这中间的点和左端点的s[i][j]就对于当前的k满足条

尺取法的应用

尺取法其实是一种很简单的算法,思想原来也用过,但一直不知道..这两天恰好做了两道有关尺取法的题,就来总结一下. 首先,什么是尺取法?尺取法通常是指对数组保存一对下标(起点.重点),然后根据实际情况交替推进两个端点直到得出答案的方法,因为这种方法像尺取虫的爬行方式所以得名.其实就是求在一个线性的数组上求关于区间的问题.由于只对区间的两个端点进行改变,所以中间部分就不需要进行维护更新了,只要维护两端即可.可以大大降低复杂度. 例题一:poj3061 给定长度为n的整数数列以及整数S,求出总和不小于S

51nod-1686 第K大区间(二分+尺取法)

题目链接: 第K大区间 基准时间限制:1 秒 空间限制:131072 KB 定义一个区间的值为其众数出现的次数.现给出n个数,求将所有区间的值排序后,第K大的值为多少. Input 第一行两个数n和k(1<=n<=100000,k<=n*(n-1)/2) 第二行n个数,0<=每个数<2^31 Output 一个数表示答案. Input示例 4 2 1 2 3 2 Output示例 2 题意: 思路: 先把数组都离散为[1,n]的数,注意相等的;再二分答案t,check区间众数

POJ 3061  Subsequence   尺取法   挑战146页

---恢复内容开始--- Subsequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10487   Accepted: 4337 Description A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 10