zoukankan      html  css  js  c++  java
  • 2019HDU多校第一场 String 贪心

    题意:给你一个字符串,问是否存在一个长度为m的子序列,子序列中对应字符的数目必须在一个范围内,问是否存在这样的字符串?如果存在,输出字典序最小的那个。

    思路:贪心,先构造一个序列自动机,序列自动机指向在它后面离它最近的某个字符的位置。对于当前位置,从a开始枚举字符,如果答案串的下个位置填这个字符可以,就立马填上这个字符,最后看一下贪心构造的字符串长度是不是m就可以了。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    int cnt[26], last[26], l[26], r[26];
    int ssum[maxn][26], Next[maxn][26];
    int n, m, tot;
    char s[maxn], ans[maxn];
    bool valid(int x) {
    	if(x == n + 1) {
    		for (int i = 0; i < 26; i++) {
    			if(cnt[i] >= l[i] && cnt[i] <= r[i]) continue;
    			return 0;
    		}
    		if(tot != m) return 0;
    		return 1;
    	}
    	bool flag = 1;
    	cnt[s[x] - 'a']++;
    	tot++;
    	for (int i = 0; i < 26; i++) {
    		if(ssum[x + 1][i] + cnt[i] >= l[i] && cnt[i] <= r[i]) continue;
    		else flag = 0;
    	}
    	int tmp = 0;
    	for (int i = 0; i < 26; i++) {
    		tmp += max(l[i] - cnt[i], 0);
    	}
    	if(m - tot > n - x + 1) flag = 0;
    	if(m - tot < tmp) flag = 0;
    	if(flag == 0) {
    		tot--;
    		cnt[s[x] - 'a']--;
    		return 0;
    	}
    	return 1;
    }
    int main() {
    	while(~scanf("%s", s + 1)) {
    		tot = 0;
    		scanf("%d", &m);
    		for (int i = 0; i < 26; i++) {
    			scanf("%d%d", &l[i], &r[i]);
    		}
    		n = strlen(s + 1);
    		memset(ssum[n + 1], 0, sizeof(ssum[n + 1]));
    		memset(cnt, 0, sizeof(cnt));
    		for (int j = 0; j < 26; j++) last[j] = n + 1;
    		for (int i = n; i >= 1; i--) {
    			for (int j = 0; j < 26; j++) {
    				ssum[i][j] = ssum[i + 1][j];
    				Next[i][j] = last[j];
    			}
    			ssum[i][s[i] - 'a']++;
    			last[s[i] - 'a'] = i;
    		}
    		for (int i = 0; i < 26; i++)
    			Next[0][i] = last[i];
    		int pos = 0;
    		while(pos <= n && tot < m) {
    			bool flag = 0;
    			for (int j = 0; j < 26; j++) {
    				if(valid(Next[pos][j])) {
    					ans[tot] = 'a' + j;
    					pos = Next[pos][j];
    					flag = 1;
    					break;
    				}
     			}
     			if(flag == 0) break;
    		}
    		if(tot == m) {
    			ans[tot + 1] = 0;
    			printf("%s
    ", ans + 1);
    		} else {
    			printf("-1
    ");
    		}
    	}
    }
    

      

  • 相关阅读:
    2013工作回望
    在Skyline 控件上面显示Web信息窗体
    Extjs xtype 为lable 设置
    纪念第一篇博客
    前端技术学习经验分享(第二、三天---学习过程)
    前端技术学习经验分享(第一天---布置学习环境)
    JS开发HTML5游戏《悠悠考拉》(三)
    JS开发HTML5游戏《悠悠考拉》(二)
    JS开发HTML5游戏《悠悠考拉》(一)
    产品经理C端转B端,我后悔了
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11228805.html
Copyright © 2011-2022 走看看