题意:给你一个字符串,问是否存在一个长度为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\n", ans + 1);
} else {
printf("-1\n");
}
}
}

  

2019HDU多校第一场 String 贪心的更多相关文章

  1. 2019HDU多校第一场1001 BLANK (DP)(HDU6578)

    2019HDU多校第一场1001 BLANK (DP) 题意:构造一个长度为n(n<=10)的序列,其中的值域为{0,1,2,3}存在m个限制条件,表示为 l r x意义为[L,R]区间里最多能 ...

  2. [2019HDU多校第一场][HDU 6578][A. Blank]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578 题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有 ...

  3. [2019HDU多校第一场][HDU 6580][C. Milk]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6580 题目大意:\(n\times m\)大小的方格上有\(k\)瓶水,喝完每瓶水都需要一定的时间.初 ...

  4. [2019HDU多校第一场][HDU 6584][G. Meteor]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6584 题目大意:求所有满足\(0<\frac{p}{q}\leq1, gcd(p,q)=1,p\ ...

  5. [2019HDU多校第一场][HDU 6590][M. Code]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6590 题目大意(来自队友):二维平面上有\(n\)个点,每个点要么是黑色要么是白色,问能否找到一条直线 ...

  6. [2019HDU多校第一场][HDU 6588][K. Function]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6588 题目大意:求\(\sum_{i=1}^{n}gcd(\left \lfloor \sqrt[3] ...

  7. 2019HDU多校第一场 BLANK DP

    题意:有四种数字,现在有若干个限制条件:每个区间中不同的数字种类必须是多少种,问合法的方案数. 思路: 定义 dp[i][j][k][t] 代表填完前 t 个位置后,{0,1,2,3} 这 4 个数字 ...

  8. 2019HDU多校第一场 6582 Path 【最短路+最大流最小割】

    一.题目 Path 二.分析 首先肯定要求最短路,然后如何确定所有的最短路其实有多种方法. 1 根据最短路,那么最短路上的边肯定是可以满足$dist[from] + e.cost = dist[to] ...

  9. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

随机推荐

  1. Swoole 简单学习(2)

    Swoole 简单学习(2) swoole之tcp服务器: //创建tcp服务器new swoole_server(string $host,int $port,int $mode=SWOOLE_PR ...

  2. 前端学习(三十四)对象&模块化(笔记)

    人,工人 //类的定义    function Person(name,age){ //构造函数        //工厂模式        //1.原料        //var obj = new ...

  3. css: IE没法调整那些使用px作为单位的字体大小

    <style type="text/css"> h1{font-size:40px;} h3{font-size:30px;} p{font-size:14xp;} & ...

  4. 更好的在 Git 项目中保存大文件(Git LFS 的使用)

    珠玉在前, 大家可以参考 Git LFS的使用 - 简书 为什么要用 Git LFS 原有的 Git 是文本层面的版本控制, 为代码这种小文件设计的, 保存大文件会导致 repo 非常臃肿, push ...

  5. 配置jdpc连接池对象

  6. day07作业猜年龄游戏

    # 给定年龄,用户可以猜三次年龄 # # 年龄猜对,让用户选择两次奖励 # # 用户选择两次奖励后退出 get_prize_dict = {} # 获取的奖品信息 age = 18 inp_count ...

  7. pycharm html 注释

    修改方式:如图修改成值None以后,command+/快捷键,html注释的符号就是<!-- 注释内容 -->:为Jinja2的时候,注释符号就是{# 注释内容 #} 修改成None时,H ...

  8. 查完数据库order_by后跟[:9]切片取前9位的值

  9. SpringMvc中乱码问题的解决

    一:如果是前台传递的数据有问题. 在tomcat的service.xml中加上: URIEncoding="UTF-8" <Connector URIEncoding=&qu ...

  10. Linux配置postfix

    启动报错:主机名不能以数字开头,否则报错