大体题意:
给你一个字符串,和一个数m ,要求在这个字符串中选出一些位置,使得任意连续的长度为m 的字符串中至少包括一个这些位置的字符!输出这些字符组成字符串的最小字典序!
思路:
借鉴了学长的博客!
感觉很巧妙:
枚举最后一个字母id!
然后开始扫这个字符串,如果这个字符小于 id 加入到ans里
如果等于id 先用栈记录一下,为什么用栈呢?因为最后用的时候肯定是用最远的一个,栈最后加入的就是最远的!
如果跑了长度为m 了还是没找到 比id 小的,就处理 等于id的 。
这个栈里第一个元素,如果位置 在那个长度为m 的区间内 就是合法的!
然后输出记录的结果即可!
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000 + 10;
char s[maxn];
int len,m;
set<int>ans;
stack<int>sk;
bool ok(int id){
ans.clear();
while(!sk.empty())sk.pop();
int sum = 0;
for (int i = 0; i < len; ++i){
if (s[i] < id+'a')ans.insert(i),sum = 0;
else if (s[i] == id+'a')sk.push(i),++sum;
else ++sum;
if (sum == m){
if (sk.empty())return 0;
int pos = sk.top();
if (pos >= i-m+1 && pos <= i)ans.insert(pos);
else return 0;
sum = i-pos;
// if (i == 1)printf("sum = %d\n",sum);
}
}
return 1;
}
int main(){
scanf("%d",&m);
scanf("%s",s);
len = strlen(s);
for (int i = 0; i < 26; ++i){
if (ok(i)) break;
}
string t = "";
while(!ans.empty()){
t += s[*(ans.begin())];
ans.erase(ans.begin());
}
sort(t.begin(),t.end());
printf("%s\n",t.c_str());
return 0;
}