[codeforces 1296E2] String Coloring (hard version) 很牛的最长上升子序列的写法+还能记录子序列中的元素
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.ml/contest/1296/problem/E2
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
E2 - String Coloring (hard version) | GNU C++11 | Accepted | 46 ms | 800 KB |
//将e1的思路用在e2上,先不论超时,就是感觉有些混乱。
//根据题目提供的数据范畴,能猜到算法的时间复杂度是O(26*n). 26个字母
//思路同https://blog.csdn.net/caowenbo2311694605/article/details/104181983摘抄如下
/*
可以想出其实本题就是请你找出
有多少个非递减子序列(最小)
很简单最多有26个 因为只有26个字母
我一开始的考虑是每次找最长非递减子序列 然后去掉 再找
最多找26次 但是我不会输出最长非递减子序列的元素
后来看了下别人的代码(发现贪心的考虑是多余的)
然后就很简单了
直接把每个元素放入能放的序列就好了(cf的tag太坑了)
*/
//算法写得很不错,比一般编程模板介绍的最长上升子序列的写法要牛。若看不懂,可跟踪代码。
#include <stdio.h>
#define maxn 200010
char s[maxn],pre[30];
int color[maxn];
int max(int a,int b){
return a>b?a:b;
}
int main(){
int i,j,n,ans=0;
scanf("%d%s",&n,s+1);
for(i=1;i<=n;i++)
for(j=1;j<=26;j++)//26个字母,故颜色最大值最多是26
if(s[i]>=pre[j]){//s[i]当前值要比 之前值 大或等于
pre[j]=s[i],color[i]=j,ans=max(ans,j);
break;
}
printf("%d\n%d",ans,color[1]);
for(i=2;i<=n;i++)printf(" %d",color[i]);
printf("\n");
return 0;
}