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; } }