题解 [AGC026E] Synchronized Subsequence

传送门

  • 涉及到最大/小化两个字符串的字典序时,可以发现当某个前缀相同时应该比较后缀,所以可以考虑从后往前 DP

那么从后往前 DP
\(f_i\) 为从 \([i, n]\) 中能得到了最大子序列
那么转移考虑删不删 \(i\)
具体还是见题解,[敷衍脸]

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 6010
#define ll long long
//#define int long long

int n;
string dp[N], s;
int a[N], b[N], id[N], tot;

signed main()
{
	freopen("c.in", "r", stdin);
	freopen("c.out", "w", stdout);
	ios::sync_with_stdio(0);

	cin>>n>>s;
	for (int i=1,pos=0; i<=n; ++i) {
		while (s[pos]!='a') ++pos;
		a[i]=pos; id[pos]=i; ++pos;
	}
	for (int i=1,pos=0; i<=n; ++i) {
		while (s[pos]!='b') ++pos;
		b[i]=pos; id[pos]=i; ++pos;
	}
	for (int i=n; i; --i) {
		dp[i]=dp[i+1];
		if (a[i]<b[i]) {
			for (int j=i+1; j<=n; ++j) if (min(a[j], b[j])>b[i]) {
				dp[i]=max(dp[i], "ab"+dp[j]);
				break;
			}
			dp[i]=max(dp[i], string("ab"));
		}
		else {
			int lst=a[i], pos=b[i]+1;
			for (; pos<lst; ++pos)
				if (s[pos]=='b')
					lst=max(lst, a[id[pos]]);
			string tem;
			for (int j=b[i]; j<=lst; ++j)
				if (id[j]>=i && b[id[j]]<a[id[j]])
					tem+=s[j];
			dp[i]=max(dp[i], tem+dp[id[lst+1]]);
		}
	}
	cout<<dp[1]<<endl;

	return 0;
}
posted @ 2022-06-13 17:59  Administrator-09  阅读(1)  评论(0编辑  收藏  举报