题意:一个项链长度为N,项链的珠子有三种可能的颜色:红白蓝。如果从某处将项链切开将会得到一条珠串,从左右两端分别寻找最长的同色串(白色即可以当红色用也可以当白色用),求这二者长度和的最大值。
解题思路:
- 将项链看作一个环形链表,用一个长度为N的整形数组来代表这个链表(红色用1代表,蓝色用-1代表,白色用0代表)
- 设一个变量index代表项链切开的位置
- 从index开始向前(或者向后)遍历,直到找到第一个不同色的点,可以得到其长度a,其中a<=N
- 从index开始向后(或者向前)遍历,直到找到第一个不同色的点,可以得到其长度b,其中a+b<=N
- 找同色串的过程:边遍历边求和,这个和在遇到第一个不同色的点之前都是单调的
- 循环遍历index,输出a+b的最大值
代码:
/*
ID: zc.rene1
LANG: C
PROG: beads
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * necklace_string;
int * necklace_int;
int number;
int count_left(int index, int max_num){
int num=0, sum=0, i;
while(num<max_num){
//move left
if(index==0) index=number-1;
else index--;
if(sum==0){
num++;
sum+=necklace_int[index];
}
else if(sum<0){
if(necklace_int[index]<=0){
num++;
sum+=necklace_int[index];
}
else{
break;
}
}
else{
if(necklace_int[index]>=0){
num++;
sum+=necklace_int[index];
}
else{
break;
}
}
}
return num;
}
int count_right(int index, int max_num){
int num=0, sum=0, i;
while(num<max_num){
//move right
if(index==number) index=0;
if(sum==0){
num++;
sum+=necklace_int[index];
}
else if(sum<0){
if(necklace_int[index]<=0){
num++;
sum+=necklace_int[index];
}
else{
break;
}
}
else{
if(necklace_int[index]>=0){
num++;
sum+=necklace_int[index];
}
else{
break;
}
}
index++;
}
return num;
}
int break_necklace(){
int left, right, max=0;
int index;
for(index=0;index<number;index++){
left=count_left(index, number);
right=count_right(index, number-left);
if((left+right)>=max) max=(left+right);
}
return max;
}
void make_int_necklace(){
//red---(1) blue---(-1) white---(0)
int i;
for(i=0;i<number;i++){
if(necklace_string[i]=='r') necklace_int[i]=1;
else if(necklace_string[i]=='b') necklace_int[i]=-1;
else necklace_int[i]=0;
}
}
int main(void){
int result;
FILE *fin=fopen("beads.in", "r");
FILE *fout=fopen("beads.out", "w");
fscanf(fin, "%d", &number);
necklace_string=(char *)malloc(sizeof(char)*(number+1));
necklace_int=(int *)malloc(sizeof(int)*number);
memset(necklace_string, 0, sizeof(char)*(number+1));
memset(necklace_int, 0, sizeof(int)*number);
fscanf(fin, "%s", necklace_string);
make_int_necklace();
result=break_necklace();
fprintf(fout, "%d\n", result);
return 0;
}