Educational Codeforces Round 38 F. Erasing Substrings DP

版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82960692

Description
给你一个长度为n的串,K次操作 ( K = l o g 2 n ) (K=⌊log2​n⌋) ,第i次操作去掉长度为2i−1的串,求最后剩下的字典序最小的串。


Sample Input
adcbca


Sample Output
aba


首先它是不会有覆盖的情况的,
然后你考虑DP吧,设f[i][j]为有i位,删除的状态为j的最优字符串。
可以 O ( n 3 l o g n ) O(n^3log n) ,考虑用hash来优化它,可以做到 O ( n 2 l o g 2 n ) O(n^2log^2 n)
然后我认为这很极限了,但好像是会T的。
那你再贪婪的考虑一下,对于所有长度为i的,你肯定是选取字典序最优的。
于是就可以把这个转成一个bool,dp[i][j]表示长度为i的状态为j是否最优。
具体转移看代码吧。。。
哦,那你就可以 O ( n 2 l o g n ) O(n^2log n)


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
int _min(int x, int y) {return x < y ? x : y;}
int _max(int x, int y) {return x > y ? x : y;}
int read() {
	int s = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
	return s * f;
}

bool f[5100][5100];
char ss[5100];

int main() {
	scanf("%s", ss + 1);
	int n = strlen(ss + 1);
	int u = log2(n);
	for(int i = 0; i < (1 << u); i++) f[0][i] = 1;
	for(int i = 1; i <= n - (1 << u) + 1; i++) {
		int minn = 26;
		for(int j = 0; j < (1 << u); j++) f[i][j] = f[i - 1][j];
		for(int j = 0; j < (1 << u); j++) if(f[i][j]) minn = _min(minn, ss[i + j] - 'a' + 1);
		for(int j = 0; j < (1 << u); j++) if(f[i][j] && minn != ss[i + j] - 'a' + 1) f[i][j] = 0;
		for(int j = 0; j < (1 << u); j++) {
			for(int k = 1; k <= u; k++) if((j >> k - 1 & 1)){
				f[i][j] |= f[i][j ^ (1 << k - 1)];
			}
		} printf("%c", minn + 'a' - 1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xgc_woker/article/details/82960692