https://codeforces.com/contest/1422/problem/E
给一个字符串,可以选择相同而且相邻的字母删除,问每个后缀操作后字典序最小的字符串;
选择从后往前遍历,如果当前的字母和上一个一样就可以选择删,判断一下这个和后面的字幕哪个大决定删不删;当可以删的时候,如果删掉更优,就只要删掉当前的两个,如果之前也有同样的字母因为前面已经判断并操作过,所以可以直接用之前的答案不用向后递归
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
struct str
{
string per,suf;
bool inc = false;
int len = 0;
void inser(char ch)
{
if(per.size()>0 && ch!=per[0])
inc = ch < per[0];
len++;
if(suf.size()<2)
suf = ch + suf;
per = ch + per;
if(per.size()>10)
per.pop_back();
}
} ans[maxn];
string s;
int main()
{
cin >> s;
//ans[s.length() - 1].per = ans[s.length() - 1].suf = s[s.length() - 1];
for (int i = s.length() - 1; i >= 0; i--)
{
char ch = s[i];
//ans[i] = ans[]
if(i+1<s.length() && s[i]==s[i+1])//能删
{
ans[i] = ans[i + 2];
if(ans[i].inc && ch == ans[i].per[0] || ch < ans[i].per[0])
ans[i].inser(ch), ans[i].inser(ch);
}else{
ans[i] = ans[i + 1];
ans[i].inser(ch);
}
}
for (int i = 0; i < s.length(); i++)
{
cout << ans[i].len << ' ';
if(ans[i].len>10)
cout << ans[i].per.substr(0, 5) << "..." << ans[i].suf << endl;
else
cout << ans[i].per << endl;
}
}