看似简单的字符串处理,不过直接暴力法是会超时的。
故此需要优化,这里使用周期优化。
研究过数列序列的都知道,其实序列反复调用另外一个序列得到一个新的序列,都会出现周期的,问题是周期何时出现,如果利用这个周期。
这就需要分开每个数,使用一个新的数列记录每个数的周期,利用这个周期截去一大段数据,那么剩下的数据就很好处理了。
因为所有的周期数总和都不会超过n,数列的长度的,所以时间效率可以达到O(n),常数项为2.
其他难度,我觉得相对新手来说,就是执行的细节最困难了,比如下标的准确性,如何移动数据等,考个人的编程功底了。
#include <stdio.h> #include <iostream> #include <string> using namespace std; int keys[201]; int keysCycle[201]; char str[205]; char res[205]; int n, repeat; void getCycle()//原始暴力法超时,需要利用周期优化 { memset(keysCycle, 0, sizeof(int)*(n+1)); for (int i = 1; i <= n; i++) { if (!keysCycle[i]) { int c = 1, j = i; while (keys[j] != i) { j = keys[j]; c++; } j = i; keysCycle[j] = c; while (keys[j] != i) { j = keys[j]; keysCycle[j] = c; } } } } int main() { while (scanf("%d", &n) && n) { for (int i = 1; i <= n; i++) { scanf("%d", &keys[i]); } getCycle(); while (scanf("%d", &repeat) && repeat) { gets(str); //We don't use the first 0 index int len = strlen(str); while (len <= n) { str[len++] = ' '; }//patch the ending with ' ' while len <= n str[len] = '\0'; //put back the '\0' ending character for (int i = 1; i <= n; i++) { int rep = repeat % keysCycle[i]; int j = i; while (rep--) j = keys[j]; res[j] = str[i]; } for (int i = 1; i <= n; i++) { putchar(res[i]); } putchar('\n'); } putchar('\n'); } return 0; }
POJ 1026 Cipher 题解
时间: 2024-11-06 16:58:23