标签:char s break mic 调整 next数组 pre printf return 长度
题目描述
输入
输出
样例输入
5
1 2 2 2 5
样例输出
ababb
题解
逆模拟KMP
首先有个易证的常用结论:1~n的最短循环节长度等于n-next[n],其中next为KMP算法中的next数组。
那么我们可以从前往后扫一遍。
当next不等于0时,由于next的定义为最长公共前后缀的长度,因此可以直接在前面的部分找到(s[next[i]])。由于题目保证有解,因此无需验证其正确性。
当next等于0时,考虑KMP算法求next的过程:对于上一个匹配位置,如果其下一个字符不等于当前字符,则当前匹配位置调整到其next的位置。如此循环直到下一个字符等于当前字符或者当前匹配位置为-1。然后next等于当前匹配位置+1。
由于当前的next等于0,意味着上一个匹配位置的任意的next的下一个字符都不等于当前字符。此时只需要循环向前重复找next的过程,并把下一个位置的字符设为不可选择。由于要求字典序最小,所以当前字符即为可以选择的字符中字典序最小的字母。
时间复杂度$O(26n)$
#include <cstdio> #include <cstring> int next[100010] , vis[26]; char str[100010]; int main() { int n , i , j; scanf("%d" , &n); next[0] = -1; for(i = 1 ; i <= n ; i ++ ) { scanf("%d" , &next[i]) , next[i] = i - next[i]; if(next[i]) str[i] = str[next[i]]; else { for(j = next[i - 1] ; ~j ; j = next[j]) vis[str[j + 1] - ‘a‘] = i; for(j = 0 ; j < 26 ; j ++ ) if(vis[j] != i) break; str[i] = j + ‘a‘; } } printf("%s\n" , str + 1); return 0; }
标签:char s break mic 调整 next数组 pre printf return 长度
原文地址:http://www.cnblogs.com/GXZlegend/p/7559669.html