题解 洛谷 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;
}

浙公网安备 33010602011771号