先来介绍一下尺取法。尺取法,顾名思义,像尺子一样,一块一块的截取。是不是解释的有点让人纳闷~。。没关系,下面我们通过这个题目来体会尺取法的魅力。
题目翻译:
给定长度为n的数列整数a0,a1,a2,a3 ….. an-1以及整数S。求出综合不小于S的连续子序列的长度的最小值。如果解不存在,则输出0。
限制条件:
10
0
S<10^8
这里我们拿第一组测试数据举例子,即 n=10, S = 15, a = {5,1,3,5,10,7,4,9,2,8}
这幅图便是尺取法怎么“取”的过程了。
整个过程分为4步:
1.初始化左右端点
2.不断扩大右端点,直到满足条件
3.如果第二步中无法满足条件,则终止,否则更新结果
4.将左端点扩大1,然后回到第二步
用尺取法来优化,使复杂度降为了O(n)。
最后,再给一个尺取法的定义以便更好理解:返回的推进区间开头和结尾,求满足条件的最小区间的方法称为尺取法。
以上为网上关于尺取法的原理介绍,还是比较好理解的,邢如蚯蚓的爬动。
直接上代码:
#include<iostream>
#include<algorithm>
using namespace std;
int const MAXN = 10;
int const S = 15;
int sequence[MAXN] = { 16,4,9,2,8,5,1,3,4,12,};
int slove(int sequence[])
{
int s = 0, t = MAXN, sum = 0, i = 0;
int res = MAXN + 1;
while (1)
{
while (sum < S && i < MAXN)
{
sum += sequence[i++];
}
if (sum < S)
{//如果全部加起来都
return res;
}
res = min(res, (i - s));//获取尺子长度
if (res > MAXN)
{
printf("not find \n");
return res;
}
sum -= sequence[s];//尺子头往后挪一个
s++;//尺子的起点
}
}
int main(int argc)
{
int res = slove(sequence);
printf("res is %d\n", res);
return 0;
}
一道题
描述
如果一个字符串恰好包含2个’h’、1个’i’和1个’o’,我们就称这个字符串是hiho字符串。
例如”oihateher”、”hugeinputhugeoutput”都是hiho字符串。
现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个。
输入
字符串S
对于80%的数据,S的长度不超过1000
对于100%的数据,S的长度不超过100000
输出
找到S的所有子串中,最短的hiho字符串是哪个,输出该子串的长度。如果S的子串中没有hiho字符串,输出-1。
样例输入
happyhahaiohell
样例输出
5
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int ch[100005], ci[100005], co[100005];
bool check(int pos, int a, int b, int c)
{
return ch[pos] <= a - 2 && ci[pos] <= b - 1 && co[pos] <= c - 1;
}
int main()
{
string s;
cin >> s;
int n = s.length();
ch[0] += (s[0] == 'h');
ci[0] += (s[0] == 'i');
co[0] += (s[0] == 'o');
int last = 0, min_len = INF;
for (int i = 1; i < n; i++)
{
ch[i] = ch[i - 1] + (s[i] == 'h');
ci[i] = ci[i - 1] + (s[i] == 'i');
co[i] = co[i - 1] + (s[i] == 'o');
if (ch[i] >= 2 && ci[i] >= 1 && co[i] >= 1)
{
while (last < i && check(last, ch[i], ci[i], co[i]))
{
last++;//找到最短的那个字符间距
}
if (ch[i] - ch[last - 1] == 2 &&
ci[i] - ci[last - 1] == 1 &&
co[i] - co[last - 1] == 1)
min_len = min(min_len, i - last + 1);
}
}
if (min_len != INF)
cout << min_len << endl;
else
cout << -1 << endl;
return 0;
}
恰好2个’h’,1个’i’,1个’o’。