【题解】AGC007E Shik and Copying String(贪心)

【题解】AGC007E Shik and Copying String(贪心)

刚开始看完题以为是一个老鼠进洞模型,不过发现这里还要求不同种类的匹配不可香蕉,而且代价不是一定的...

追踪最终得到的串\(T\)每个字符\(T_i\)的来源,可以发现是一条引向\(p<i\)的折线,可以发现这条直线覆盖的\(x\)轴上的长度越小越好,最终答案是所有形如这样的匹配的折线中拐点最多的折线的拐点个数。用一个双端队列维护当前匹配的拐点\(x\)坐标,从后向前考虑\(T\)中每个字符的匹配。

设当前枚举到\(T_i\),而\(T_{i+1}\)匹配到\(S_p\),双端队列中维护了所有拐点的坐标。考虑最大的\(p'<p,S_{p'}=T_i\)

  • \(p=p'\),那么\(T_{i+1}\)可以直接从\(T_i\)这里继承过去,那么\(T_i\)匹配的拐点是点i+上一个折线所有坐标\(< i\)的拐点。
  • \(p\not = p'\),那么由于要保证\(x\)的跨度尽量小,新的折线最优应该是上一次的折线所有的(坐标+1)加上(可能需要的,为了匹配到这次的\(p'\))的拐弯。

代码

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;  typedef long long ll;
int n,ans;
const int maxn=1e6+5;
char S[maxn],T[maxn];
deque<int> q;
int main(){
	scanf("%d%s%s",&n,S+1,T+1);
	q.push_back(n+1);
	for(int t=n,p=n+1,offset=0;t;--t){
		int sav=p;
		while(p&&(p>t||S[p]!=T[t])) --p;
		if(p<1) puts("-1"),exit(0);
		if(sav==p){
			while(q.size()&&q.back()-offset>=t) q.pop_back();
			q.push_back(t+offset);
		}else{
			++offset;
			if(t!=p) ans=max(ans,(int)q.size()),q.push_front(p+offset);
		}
	}
	cout<<ans<<endl;
	return 0;
}

posted @ 2020-02-16 00:15  谁是鸽王  阅读(157)  评论(0编辑  收藏  举报