题解 洛谷 P5329 【[SNOI2019]字符串】

这道题老师有一天断了网让我们做,然后线下测评开了2s。。。

当时我是手打几个数据,然后找到规律的。

对于$s_i$,我们分情况讨论:

首先,如果有$s_i=s_{i+1}$,那么删除$s_i$和$s_{i+1}$结果一样,那么可以把连续相同字符压成一个,输出时从小到大输出就可以了。

然后,如果有$s_i>s_{i+1}$,那么删除$s_i$肯定比不删除$s_i$更优,所以$i$排在所有$k(>i)$的前面。

最后,如果有$s_i<s_{i+1}$,那么删除$s_i$肯定没有不删除$s_i$优,所以$i$排在所有$k(>i)$的后面。

我是用一次$dfs$解决的,只要到一个连续下降子序列(压缩后无相邻相等)的末尾就往下$dfs$在回溯时再输出当前位置,边界为到达$N$。

Code:

#include<cstdio>
int N,bg[1000003],cnt;//bg:begin,一个连续相同序列的开始
char s[1000003];
inline void dfs(int d)
{
    int t,m;
    for(t=d;s[bg[t]]>s[bg[t+1]];++t)
    {
        for(m=bg[t];m<bg[t+1];++m)
        {
            printf("%d ",m);
        }
        if(m==N+1)return;
    }
    dfs(t+1);//回溯后再输出当前位置
    for(m=bg[t];m<bg[t+1];++m)
    {
        printf("%d ",m);
    }
}
int main()
{
    scanf(" %d %s",&N,s+1);
    for(int i=1;i<=N;++i)
    {
        if(s[i]==s[i-1])continue;
        bg[++cnt]=i;//压缩
    }
    bg[++cnt]=N+1;
    dfs(1);
    return 0;
}

 

posted @ 2019-08-17 13:09  VinstaG173  阅读(185)  评论(0)    收藏  举报