看似简单的字符串处理,不过直接暴力法是会超时的。
故此需要优化,这里使用周期优化。
研究过数列序列的都知道,其实序列反复调用另外一个序列得到一个新的序列,都会出现周期的,问题是周期何时出现,如果利用这个周期。
这就需要分开每个数,使用一个新的数列记录每个数的周期,利用这个周期截去一大段数据,那么剩下的数据就很好处理了。
因为所有的周期数总和都不会超过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;
}