题目大意:给定一个字符串,求一个最短的串要求没有在该字符串的子串中出现过,如果有多个,输出字典序最小的那一个。

题解:倒着跑一遍原字符串(以下编号为$1\sim n$),按出现了所有$26$个字母来分段,把完整的段从左到右编号,第$i$段为$[l_i,r_i]$,答案的长度就是分成的完整的段$+1$,考虑字典序最小,第一个字母一定是$[1,l_i)$中最小的没有出现的字符;对于第$i$位答案,令$x$为$ans_{i-1}$在$[l_{i-1},r_{i-1}]$中第一次出现的位置,则$ans_i$等于在$[x,r_{i-1}]$中最小的没出现过的字符

卡点:

C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 200010
#define N maxn / 26 + 10
char s[maxn];
int l[N], r[N];
int cnt[26];
int sum[maxn][26], nxt[maxn][26];
int n, m, sz, ans;
char find(int r, int l = 0) {
for (int i = 0; i < 26; i++) if (!(sum[r][i] - sum[l][i])) return i + 97;
return 20040826;
}
int main() {
sz = sizeof cnt;
scanf("%s", s + 1);
n = strlen(s + 1);
int num = 0; r[m = 1] = n;
for (int i = n; i; i--) {
memcpy(nxt[i], nxt[i + 1], sz);
int x = s[i] - 'a';
nxt[i][x] = i;
num += cnt[x]++ == 0;
if (num >= 26) {
l[m] = i;
r[++m] = i - 1;
memset(cnt, 0, sz);
num = 0;
}
}
for (int i = 1; i <= n; i++) {
memcpy(sum[i], sum[i - 1], sz);
sum[i][s[i] - 'a']++;
}
putchar(ans = find(r[m]));
for (int i = m - 1; i; i--) putchar(ans = find(r[i], nxt[l[i]][ans - 'a']));
putchar(10);
return 0;
}

最新文章

  1. bat基础命令
  2. Android手绘效果实现
  3. max_user_connections 与 max_connections,max_connect_errors, nr_open, file-max
  4. 新一批电子商务解决方案和企业管理应用加入 VM Depot 中国站点
  5. java学用代码
  6. github在windows下的安装和基本使用
  7. Django error信息邮件通知功能配置部署
  8. 2、FreeRTOS任务相关API函数
  9. 第八周 ip通信基础回顾
  10. css 技巧 (持续更新)
  11. JDK的动态代理-----为接口进行代理
  12. vue实现筛选功能,文字选中变色
  13. ELM:ELM基于近红外光谱的汽油测试集辛烷值含量预测结果对比—Jason niu
  14. pytest的执行规则和顺序
  15. Linux FACL(文件访问控制列表)
  16. Intellij Idea出现 unable to establish loopback connection
  17. ORACLE 执行计划
  18. Resnet小记
  19. 在Docker中运行crontab
  20. Ant是什么

热门文章

  1. java多线程-概念&amp;创建启动&amp;中断&amp;守护线程&amp;优先级&amp;线程状态(多线程编程之一)
  2. linux:eth网卡对应的物理网口判断
  3. 图解HTTP总结(5)——与HTTP协作的Web服务器
  4. python-无参函数
  5. 使用shell脚本依据分区信息分批次的下载hive表格数据
  6. C语言进阶——注释符号12
  7. js石头剪刀布小游戏
  8. BurpSuite 的使用
  9. Kali Linux 搜狗输入法安装
  10. Error:Java home supplied via &#39;org.gradle.java.home&#39; is invalid