AtCoder regular contest 081 E - Don't Be a Subsequence
2017-08-21 00:22
489 查看
原题链接:http://arc081.contest.atcoder.jp/tasks/arc081_c
题目大意:给出一个小写字母构成的字符串,求满足2个条件的字典序最小的字符串:
1.不是这个字符串的子序列;
2.长度最短;
先把整个给定的字符串S倒序处理一下,每次集齐26个字母就把set清空并把这一区间划归为同一组
(令区间范围为 [ Li , Ri ] )( 1<=i<=tot)
则可以知道长度为tot的所有字符串都为S的子序列,而且存在长度为tot+1的字符串不是S的子序列,所以答案串的长度为tot+1
令串S从第 i 个字符开始的后缀为 suffix ( i )
令答案串为ans
令答案串到第 i 个字符开始的前缀第一次作为S的子序列出现的位置为 pos( i )
显然ans[ 1 ]是[ 1 , L1 )区间内没出现过的字符,否则,以这个字符为开头的长度为tot+1的字符串都是S的子序列
然后当前的问题就转化为了 获得长度为tot且不是 suffix( pos( 1 ) )的子序列的字典序最小的字符串,显然除了第一组,其他的分组仍然没有变,这样我们所求的ans[2]一定是[ pos(1) , L2)区间内没出现过的字符,否则,以这个字符ans[2]的长度为tot的字符串都是S的子序列,
如此递推处理,就会得到一个长度为tot的字符串,最后一个字符只要是[ pos(tot) ,len]区间内没有出现过的字符就是满足条件的。
显然每次在取答案串的字符的时候就可以贪心取最小的字符就可以保证是字典序最小的答案串。
代码:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
constexpr int maxn = 2000010;
char s[maxn];
set <int> S;
int nextt[maxn][30];
int now[30];
int now_tot[maxn];
void doit(){
scanf("%s",s);
int len=strlen(s);
int tot=0;
for (int i=len;i>=1;i--)
{
S.insert( s[i-1]-'a' );
now_tot[i]=tot;
if (S.size()==26)
{
tot++;
S.clear();
}
}
if (tot==0)
{
for (int i=0;i<26;i++)
if (S.count (i )==0)
{
printf("%c",i+'a');
return ;
}
}
memset(now,0,sizeof(now));
for (int i=len;i>=1;i--)
{
for (int j=0;j<26;j++)
nextt[i][j]=now[j];
now[ s[i-1]-'a' ]=i;
}
int tmp=0;
for (int i=0;i<26;i++)
if (S.count (i )==0)
{
tmp=now[i];
break;
}
printf("%c",s[tmp-1]);
for (int i=1;i<tot;i++)
{
for (int j=0;j<26;j++)
if (now_tot [ nextt[ tmp ][ j ] ]==now_tot [ tmp ] -1 )
{
tmp=nextt[ tmp ][ j ];
printf("%c",s[tmp-1]);
break;
}
}
for (int i=0;i<26;i++)
if (nextt[ tmp ][ i ]==0)
{
printf("%c",i+'a');
break;
}
}
int main(){
doit();
return 0;
}
题目大意:给出一个小写字母构成的字符串,求满足2个条件的字典序最小的字符串:
1.不是这个字符串的子序列;
2.长度最短;
先把整个给定的字符串S倒序处理一下,每次集齐26个字母就把set清空并把这一区间划归为同一组
(令区间范围为 [ Li , Ri ] )( 1<=i<=tot)
则可以知道长度为tot的所有字符串都为S的子序列,而且存在长度为tot+1的字符串不是S的子序列,所以答案串的长度为tot+1
令串S从第 i 个字符开始的后缀为 suffix ( i )
令答案串为ans
令答案串到第 i 个字符开始的前缀第一次作为S的子序列出现的位置为 pos( i )
显然ans[ 1 ]是[ 1 , L1 )区间内没出现过的字符,否则,以这个字符为开头的长度为tot+1的字符串都是S的子序列
然后当前的问题就转化为了 获得长度为tot且不是 suffix( pos( 1 ) )的子序列的字典序最小的字符串,显然除了第一组,其他的分组仍然没有变,这样我们所求的ans[2]一定是[ pos(1) , L2)区间内没出现过的字符,否则,以这个字符ans[2]的长度为tot的字符串都是S的子序列,
如此递推处理,就会得到一个长度为tot的字符串,最后一个字符只要是[ pos(tot) ,len]区间内没有出现过的字符就是满足条件的。
显然每次在取答案串的字符的时候就可以贪心取最小的字符就可以保证是字典序最小的答案串。
代码:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
constexpr int maxn = 2000010;
char s[maxn];
set <int> S;
int nextt[maxn][30];
int now[30];
int now_tot[maxn];
void doit(){
scanf("%s",s);
int len=strlen(s);
int tot=0;
for (int i=len;i>=1;i--)
{
S.insert( s[i-1]-'a' );
now_tot[i]=tot;
if (S.size()==26)
{
tot++;
S.clear();
}
}
if (tot==0)
{
for (int i=0;i<26;i++)
if (S.count (i )==0)
{
printf("%c",i+'a');
return ;
}
}
memset(now,0,sizeof(now));
for (int i=len;i>=1;i--)
{
for (int j=0;j<26;j++)
nextt[i][j]=now[j];
now[ s[i-1]-'a' ]=i;
}
int tmp=0;
for (int i=0;i<26;i++)
if (S.count (i )==0)
{
tmp=now[i];
break;
}
printf("%c",s[tmp-1]);
for (int i=1;i<tot;i++)
{
for (int j=0;j<26;j++)
if (now_tot [ nextt[ tmp ][ j ] ]==now_tot [ tmp ] -1 )
{
tmp=nextt[ tmp ][ j ];
printf("%c",s[tmp-1]);
break;
}
}
for (int i=0;i<26;i++)
if (nextt[ tmp ][ i ]==0)
{
printf("%c",i+'a');
break;
}
}
int main(){
doit();
return 0;
}
相关文章推荐
- AtCoder Regular Contest 081 E - Don't Be a Subsequence(字符串DP)
- (dp)AtCoder Regular Contest 081 E - Don't Be a Subsequence
- 【AtCoder】ARC 081 E - Don't Be a Subsequence
- Atcoder Regular Contest 081 总结
- AtCoder Regular Contest 081 F - Flip and Rectangles 动态规划
- AtCoder Regular Contest 081 D - Coloring Dominoes
- AtCoder Regular Contest 077
- Atcoder Regular contest 085F NRE 线段树+DP
- AtCoder Regular Contest 078 C
- AtCoder Regular Contest 079 C D E
- AtCoder Regular Contest 069 D
- AtCoder Regular Contest 090
- AtCoder Regular Contest 080 F - Prime Flip 线性筛+匈牙利算法
- AtCoder Regular Contest 065 Shuffling 动态规划
- AtCoder Regular Contest 092 B Two Sequences
- 【杂题】[AtCoder Regular Contest 092 D] Two Sequences
- AtCoder Regular Contest 095E - Symmetric Grid
- AtCoder Regular Contest 059 F Unhappy Hacking
- Atcoder regular Contest 073(C - Sentou)
- AtCoder Regular Contest 067 F - Yakiniku Restaurants