题目链接:http://poj.org/problem?id=2541
题目大意:给定一个01序列,0代表雨天,1代表晴天。现在我们希望预测N+1天的天气,预测的方法是寻找某个子串使得这个子串等于天气序列的后缀,要求找到的子串长度最长,字典序最小,那个子串的下一个值就是N+1的值。其实挺好理解的,现实中就是要找最多的相同天气,然后就可以预测。
解题思路:这题可用KMP解。题目要求的是某个子串和后缀天气相同,那我们把这个串反转,不久是找某个子串和前缀相同,而且序列长度是【13,1】,然后就可以计算Next数组,并找到最大的next值也就是和前缀相同的最大长度,然后就没有然后了。这样复杂度是N*L,最坏的时候操作数超过100亿,如果数据强一点,我这个方法肯定过不了,但是poj总是误人子弟,也就水过了。
测试数据:
27 1
111111111111101111111111111
1101110010
代码:
#include <stdio.h>
#include <string.h>
#define MAX 1100000
int next[MAX],n,L,len;
char arr[MAX],brr[MAX];
void Reverse(char *a,char *b,int len){
for (int i = 0; i < len; ++i)
b[i] = a[len-i-1];
}
char GetNext(char *brr,int len) {
int i = 0,j = -1;
int maxx = 0,maxi;
next[0] = -1;
while (i < len) {
if (j == -1 || brr[i] == brr[j])
i++,j++,next[i] = j;
else j = next[j];
if (next[i] <= 13 && maxx < next[i])
maxx = next[i],maxi = i - next[i] - 1;
if (next[i] > 13) break;
}
if (maxx == 0) return '0';
else return brr[maxi];
}
int main()
{
int i,j,k;
while (scanf("%d%d",&n,&L) != EOF) {
scanf("%s",arr);
for (i = 0; i < L; ++i) {
len = n + i;
Reverse(arr,brr,len);
arr[len] = GetNext(brr,len);
}
for (i = n; i < L + n; ++i)
printf("%c",arr[i]);
printf("\n");
}
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。