题解:P17872 [FJCPC 2026] 限号出行
题意
给定一个长度为
思路
标签:贪心,动态规划。
首先因为要求提取的子序列的字典序最小,容易想到从前往后按字符贪心。假设上一个字符的位置为
找到一个新的字符
记
那么把每个位置上的 DP 值预处理出来,就可以快速判断一个选择是否合法,结合上述贪心即可。时间复杂度
代码
:::info[代码]
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+3,K=26;char c1,c2;
int T,n,m,k,to[N][K],dp[N],x,f;
string s,ans;bool bj[K][K],ok;
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>T;while(T--){
cin>>n>>m>>k>>s,s=' '+s,dp[n+1]=0;
for(int i=1;i<=m;++i) cin>>c1>>c2,bj[c1-'a'][c2-'a']=1;
for(int j=0;j<K;++j) to[n+1][j]=n+1;
for(int i=n;i>=1;--i){
dp[i]=1,x=s[i]-'a';
for(int j=0;j<K;++j){
to[i][j]=to[i+1][j];
if(!bj[x][j]) dp[i]=max(dp[i],dp[to[i][j]]+1);
}to[i][x]=i;
}x=1;for(int i=1;i<=k;++i){
ok=0;for(int j=0;j<K;++j){
if(x!=1&&bj[f][j]) continue;
if(dp[to[x][j]]>=k-i+1){
ans+='a'+j,f=j,ok=1;
x=to[x][j]+1;break;
}
}if(!ok) break;
}if(!ok)cout<<"-1\n";else cout<<ans<<'\n';
memset(bj,0,sizeof(bj)),ans="";
}return 0;
}
| 提交记录 |
|---|