去掉题目的背景:就是一个环形的串中,寻找一个最长的子串,该串由前后由俩部分组成,连续的b串和连续的r串,当然,一种颜色也可以;w可转变成任意颜色;
我的思路:比较简单的思路,但是是一个复杂度O(n^2)的算法;
先求出以每一个位置开始的最长串的长度,再找出可衔接的最长串即可;
USACO上面有更快的O(n)算法。
Holland's Frank Takes has a potentially easier solution:
/* This solution simply changes the string s into ss, then for every starting
// symbol it checks if it can make a sequence simply by repeatedly checking
// if a sequence can be found that is longer than the current maximum one.
*/
#include <iostream>
#include <fstream>
using namespace std;
int main() {
fstream input, output;
string inputFilename = "beads.in", outputFilename = "beads.out";
input.open(inputFilename.c_str(), ios::in);
output.open(outputFilename.c_str(), ios::out);
int n, max=0, current, state, i, j;
string s;
char c;
input >> n >> s;
s = s+s;
for(i=0; i<n; i++) {
c = (char) s[i];
if(c == 'w')
state = 0;
else
state = 1;
j = i;
current = 0;
while(state <= 2) {
// dont go further in second string than starting position in first string
while(j<n+i && (s[j] == c || s[j] == 'w')) {
current++;
j++;
} // while
state++;
c = s[j];
} // while
if(current > max)
max = current;
} // for
output << max << endl;
return 0;
} // main
/*
ID: nanke691
LANG: C++
TASK: beads
*/
#include<iostream>
#include <fstream>
#include<string.h>
using namespace std;
char s1[700];
int dp[355];
int main()
{
int n;
FILE *fin = fopen ("beads.in", "r");
FILE *fout = fopen ("beads.out", "w");
//while(scanf("%d",&n)==1)
//{
fscanf(fin,"%d",&n);
fscanf(fin,"%s",s1);
for(int i=0;i<n;i++)
s1[i+n]=s1[i];
s1[2*n]='\0';
//puts(s1);
int flag=0;
memset(dp,0,sizeof(dp));
for(int i=0;i<n;i++)
{
if(s1[i]=='w')
flag=1;
else flag=0;
char temp=s1[i];
for(int j=i+1;j<2*n;j++)
{
if(flag&&s1[j]!='w')
{
flag=0;
temp=s1[j];
}
if(temp==s1[j]||s1[j]=='w')
dp[i]++;
else break;
}
dp[i]++;
}
//for(int i=0;i<n;i++)
// printf("%d ",dp[i]);
//cout<<endl;
int max1=-1;
for(int i=0;i<n;i++)
{
int t=dp[i],sum;
if(t>n)
sum=dp[i]+dp[t-n];
else sum=dp[i]+dp[t+i];
if(sum>max1)
max1=sum;
if(max1>=n)
{
max1=n;
break;
}
}
fprintf(fout,"%d\n",max1);
//}
return 0;
}