去掉题目的背景:就是一个环形的串中,寻找一个最长的子串,该串由前后由俩部分组成,连续的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; }