题解 [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;
}