[hdu多校]Substring

本题是典型的“滑动窗口”题,所以借由本题复习一下“滑动窗口算法”。
1.算法本质:贪心、利用之前的状态求解当前状态。
2.适用条件:区间具有单调性,即若[L,R]满足条件, [L-1,R]必满足条件,并且[R,L+1]有可能满足条件。
3.可以解决的问题:找一个具有单调性的区间的最大值或者最小值。
在这里插入图片描述
先上代码。

#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define INF 0x3f3f3f3f
typedef long long ll;
const int maxn = 4e5+5;

using namespace std;

int k;
char s[maxn];
int main()
{
   FAST; 
   	while(cin>>k)
	{
		cin>>s+1;
		int len=strlen(s+1);
		int l=1,r=1,ans=-INF;
		int cnt[27]={0};
		
		cnt[s[1]-96]++;
		while(l<=r && r<=len)
		{
			int flag=1;
			for (int i=1; i<=26; i++)
			{ 
				if (cnt[i]>k) 
				{ 
					flag=0; 
					break; 
				} 
			}
				
			if (flag==1)
			{
				if (ans<r-l+1) ans=r-l+1;
				r++;
				cnt[s[r]-96]++;
			}
			else
			{
				cnt[s[l]-96]--;
				l++;
			}
		}
		cout<<ans<<endl;	   	
	} 
return 0;
}

后来又写了一个自认为更快地版本(然而更慢)

#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define INF 0x3f3f3f3f
typedef long long ll;
const int maxn = 4e5+5;

using namespace std;

int k;
char s[maxn];
int main()
{
   FAST; 
   	while(cin>>k)
	{
		map<char, int> cnt;
		cnt.clear();
		
		cin>>s+1;
		int len=strlen(s+1);
		int l=1,r=1,ans=-INF;
		
		cnt[s[1]]++;
		while(l<=r && r<=len)
		{
			while(cnt[s[r]]>k && l<=r) cnt[s[l++]]--;
			ans=max(ans,r-l+1);
			cnt[s[++r]]++;
		}
		cout<<ans<<endl;	   	
	} 
return 0;
}

复习一下模板

模板一:
int l=1,r=1;  //左右端点同时从最左边开始取
while(l<=r && r<=n)
{
	if (满足条件)
	{
		if (r-l+1<ans)
		{
			ans=r-l+1;
			ans_l=l, ans_r=r;
		}
		r++;  (l++)
		更新窗口
	}
	else //不满足条件
	{
		l++;  (r++)
		更新窗口
	}
}

模板二:
int l=1,r=1;  //左右端点同时从最左边开始取
讲第一个元素加入窗口,并对窗口进行更新;
while(l<=r && r<=n)
{
	while(加入a[r]后窗口不符合条件)
	{
		l++; 或者r++;
		更新窗口;  //弹出或加入元素
	}
	更新ans;
	r++; 或l++ //贪心的扩展(缩小)窗口
	更新窗口;  //弹出或加入元素
}
究竟是l++还是r++要看求的是最长区间还是最短区间

题单:
UVA 11572 Unique Snowflakes
洛谷 p1102 A-B数对
洛谷 p1638
poj 3061 Sequence
Codeforces 1042D Petya and Array
Codeforces 47E Cannon
Codeforces 939E Maximize!
Atcoder 4142 Xor Sum 2

更多讲解和题目:
https://www.luogu.com.cn/blog/Nero-Yuzurizaki/chi-qu-fa-xiao-jie

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值