原题链接
题意:t组数据,每组给一个由小写字母组成的字符串,将每个出现过的字母删减至只剩一个,输出删减后字典序最大的字符串。
该说不说,这场div3的官方题解就写的就nm离谱,明明有更好理解复杂度更低的解法,硬是要放最难理解复杂度最高的解法,无语惹。
思路:用vector存一下每个字母的下标,然后从z到a遍历,二分查找一下当前字母(比如是z)最贪心的位置,再判断一下比z小的字母下标中最后一个下标是否比这个位置小,如果存在就说明z不行,会有比z小的字母无论怎么删减也会在z前面,大概就是这个意思,细节还是看代码吧。
#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define stree SegTree[root]
#define lson SegTree[root << 1]
#define rson SegTree[root << 1 | 1]
using namespace std;
const int N = 200005;
char s[N];
bool vis[30];
int main()
{
int t;
cin>>t;
while (t--)
{
cin>>s;
int n = strlen(s);
vector<int> v[30];
for (int i = 0;i < n;i++)
{
v[s[i]-'a'].emplace_back(i);
}
int m = 0;
for (int i = 0;i < 26;i++)
{
vis[i] = 0;
if(!v[i].empty()) m++;
}
int tem = 0;
for (int i = 0;i < m;i++)
{
for (int j = 25;j >= 0;j--)
{
if (v[j].empty() || vis[j]) continue;
bool fla = 1;
int pos = *lower_bound(v[j].begin(), v[j].end(), tem);
//printf("j = %d, pos = %d\n",j, pos);
for (int k = 0;k < j;k++)
{
if (v[k].empty() || vis[k] || j==k) continue;
if (v[k].back() < pos)
{
fla = 0;
break;
}
}
if(fla)
{
printf("%c", j+'a');
tem = pos;
vis[j] = 1;
break;
}
}
}
printf("\n");
}
return 0;
}