Sherlock Puzzle
Difficulty: Hard

Sherlock Holmes is bored to death as there aren't any interesting cases to solve. Dr Watson finding it impossible to be around Sherlock goes out to get some fresh air. Just as he lays his feet out of the door, he is thrown right back into his house by the explosion in front of his apartment. The metropolitan police arrive at the scene a few minutes later. They search the place thoroughly for any evidence that could throw some light on the event that unfolded. Unable to get any clues, they call Sherlock for help. After repeated persuasion by Mycroft Holmes and Dr Watson, Sherlock agrees to look at the crime scene. 

Sherlock walks into the apartment, the walls are all black and dripping wet as the fire was recently extinguished. With his skills, he observes, deduces and eliminates the impossible. What's left after it is a simple puzzle left by an evil computer genius and the future Arch Nemesis of Sherlock, Jim Moriarty. 

Given a binary string (**S**) which contains '0's and '1's and an integer **K**,   
find the length (**L**) of the longest contiguous subsequence of (S * K) such that twice the number of zeroes is <= thrice the number of ones (2 * #0s <= 3 * #1s) in that sequence.

S * K is defined as follows:
S * 1 = S  
S * K = S + S * (K - 1)  

**Input Format**    
The first (and only) line contains an integer K and the binary string S separated by a single space. 

**Constraints**  
1 <= |S| <= 1,000,000  
1 <=  K  <= 1,000,000  

**Output Format**  
A single integer L - the answer to the test case

**Sample Input**

    2 00010

**Sample Output**

    2

**Explanation**

    S * K = 0001000010

"1" and "10" meet the requirement that 2 * #0 <= 3 * #1  
The longest one is "10", length = 2.


Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:

Editorial: 2020 September Editorial: Sherlock Puzzle
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p>For any more queries, beyond the scope of this editorial, feel free to contact our problem setter WanBo: wanbo_hackerrank@gmail.com  </p>

<p>What is the longest contiguous sub-sequence of (S * K) with (2 * number of zeroes &lt;= 3 * number of ones)?
Let replace '0' by -2 and '1' by 3:  </p>

<p>Then we need to find the longest sub-string such that the sum[i, j] &gt;= 0.  </p>

<p><strong>1)</strong> If sum(S) &gt;= 0, answer = len(S) * K</p>

<p><strong>2)</strong> If S == 1, how can we find the answer? <br>
    p[i] = S[0] + S[1] + ... + S[i]
    sum[i, j] = p[j + 1] - p[i] <br>
==&gt; For every i, we just need to find the largest j that p[j] &gt;= p[i].   </p>

<p><strong>How do we accelerate the search?</strong> <br>
 n can be as large as 10^6 so   we need to find the j for every i at least O(log n). But p[i] is not ordered, and because of this we can not use binary search directly.     </p>

<pre><code>If rmax[k] = max{p[i] | k &lt;= i &lt; n}
==&gt; rmax[0] &gt;= rmax[1] &gt;= ... &gt;= rmax[n - 1]  
</code></pre>

<p>Then for every i, we just need to find the largest k that rmax[k] &gt;= p[i]. We can solve it by binary search. We can solve this sub-problem O(nlogn).  </p>

<p>Now, can we optimize O(nlogn) to O(n)? <br>
Observe that when you find a best interval (i0,j0) and want to find a better (i1,j1) with i1 &gt; i0, there must be p[i1] &lt; p[i0] and j1 &gt; j0 (An exercise to the reader - Why?). Therefore, you increment the value of i until you find smaller value of p[i], and then increase j until rmax[j + 1] &lt; p[i]. We will increase i, j at most 2 * n times, so that we can solve it linearly.   </p>

<p><strong>3)</strong> If S &gt; 1, how do we solve this problem? <br>
If the longest subsequence is a substring of S, then we can solve it as S == 1. Else we need to maximize the length of suffix(S) + S * i + prefix(S) <br>
suffix(S)_1 + S * i + prefix(S)_1 &gt;= suffix(S)_2 + S * j + prefix(S)_2 <br>
S + S * i + S &gt; S * j ==&gt; i &gt;= j - 1. <br>
Obviously, i &gt;= j - 1, so the best i will be the (largest_i) or (largest_i - 1).   </p>

<p>How do we calculate the largest_i?  </p>

<pre><code>T = sum(suffix(S) + prefix(S))
largest_i = -T / sum(S)
</code></pre>

<p>We can set the i to largest_i and largest_i - 1, and choose the best answer.    </p>

<p>If we set i = x: <br>
    T + S * x &gt;= 0 ==&gt; T &gt;= -S * x.   </p>

<p><strong>What we need to solve is:</strong> <br>
What's the longest suffix(S) + prefix(S) that sum of this should be &gt;= -S * x  </p>

<p>==&gt; sub-problem: <br>
S[i, ..., n - 1] + S[0, ..., j] &gt;= threshold
What the maximal n - i + (j + 1)?  </p>

<p>For suffix(S): <br>
If rsum[i] = sum[i, n - 1] <br>
If i0 &lt; i1 and rsum[i0] &gt;= rsum[i1], then i1 can not be the best choice. <br>
We can maintain a monotonous sequence of suffix that:
(i0, rsum[i0]) (i1, rsum[i1]) ... <br>
i0 &lt; i1 &lt; ... <br>
sum[i0] &lt; sum[i1] &lt; ...  </p>

<p>For prefix(S): <br>
If lsum[i] = sum[0, i] <br>
If i0 &lt; i1 and lsum[i0] &lt;= lsum[i1], then i0 can not be the best choice. <br>
We can maintain a monotonous sequence of suffix that:
(i0, lsum[i0]) (i1, lsum[i1]) ... <br>
i0 &lt; i1 &lt; ... <br>
sum[i0] &gt; sum[i1] &gt; ...  </p>

<p>==&gt; <br>
Given A[] and B[], A is increasing, B is decreasing, for every A[i], how to find the largest j that B[j] &gt;= T - A[i].
This can be solve in O(n) like the method described in the case when K == 1. (exercise)    </p>

<h3>C++ Solution from the Problem Setter, WanBo </h3> 


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
typedef vector VI;
typedef pair PII;
#define MM(a,x) memset(a,x,sizeof(a));
#define ALL(x)  (x).begin(), (x).end()
#define P(x)    cerr "#b": " void PV(T a, T b) {while(a != b)cout  inline bool chmin(T &amp;a, T b) {return a &gt; b ? a = b, 1 : 0;}
template inline bool chmax(T &amp;a, T b) {return a  L, R;
    for(int i = n - 1; i &gt;= 0; i--) {
        while(!L.empty() &amp;&amp; sL[i] &gt;= L.back().x) L.pop_back();
        L.pb(mp(sL[i], n - i));
    }

    for(int i = 0; i = R.back().x) R.pop_back();
        R.pb(mp(sR[i], i + 1));
    }

    int res = 0;
    for(int i = 0; i = least) chmax(res, L[i].y);
    for(int i = 0; i = least) chmax(res, R[i].y);
    int l = 0, r = (int) R.size() - 1;
    while(l = 0) {
        while(r &gt;= 0 &amp;&amp; L[l].x + R[r].x = 0) chmax(res, L[l].y + R[r].y);
        l++;

    }
    return res;
}


int p[N];
int rmax[N];

LL solve() {
    for(int i = 0; i = 0; i--) rmax[i] = max(rmax[i + 1], p[i]);
    int mx = 0;
    int l = 0;
    int r = 0;
    for(int i = 0; i = p[l]) continue;
        int rr = -1;
        while(r = 0) {
            rr = r - i;
            r++;
        }
        r--;
        int len = rr;
        if(mx  pt(S.length() + 1, 0);
    LL res = 0;
    for(int i = 0; i = 0 &amp;&amp; chmax(res, (LL)(j - i + 1))) {
                pi = i, pj = j;
            }
        }
    return res;
}

int main() {
    cin &gt;&gt; K &gt;&gt; s;
    n = s.length();
    for(int i = 0; i = 0) {
        res = (LL) n * K;
    } else {
        int tot = 0;
        {
            int mx = 0;
            for(int i = n - 1; i &gt;= 0; i--) {
                sL[i] = sL[i + 1] + d[i];
                chmax(mx, sL[i]);
            }
            tot += mx;
        }
        {
            int mx = 0;
            for(int i = 0; i  0) sR[i] = sR[i - 1] + d[i];
                else sR[i] = d[i];
                chmax(mx, sR[i]);
            }
            tot += mx;
        }

        if(K &gt;= 2) {
            LL T = min(K - 2, tot / abs(score));
            res += n * T;
            //      P(res);
            res += crossMid(-score * T);
            chmax(res, solve());
        } else {
            res = solve();
        }
    }
    cout 

Reference solution (C++):
###C++  
```cpp  
#include <map>
#include <set>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <vector>
#include <ctime>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <cassert>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;
#define MM(a,x) memset(a,x,sizeof(a));
#define ALL(x)  (x).begin(), (x).end()
#define P(x)    cerr<<"["#x<<" = "<<x<<"]\n"
#define PP(x,i)    cerr<<"["#x<<i<<" = "<<x[i]<<"]\n"
#define P2(x,y)    cerr<<"["#x" = "<<x<<", "#y" = "<<y<<"]\n"
#define TM(a,b)    cerr<<"["#a" -> "#b": "<<1e3*(b-a)/CLOCKS_PER_SEC<<"ms]\n";
#define FOR(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define uni(v) sort(ALL(v)), v.resize(unique(ALL(v)) - v.begin())
#define mp make_pair
#define pb push_back
#define x first
#define y second
struct _ {_() {ios_base::sync_with_stdio(0);}} _;
template<class T> void PV(T a, T b) {while(a != b)cout << *a++, cout << (a != b ? " " : "\n"); cout.flush();}
template<class T> inline bool chmin(T &a, T b) {return a > b ? a = b, 1 : 0;}
template<class T> inline bool chmax(T &a, T b) {return a < b ? a = b, 1 : 0;}
const int inf = 0x3f3f3f3f;
const int mod = int(1e9) + 7;
const int N = 1111111;

string s;
int K;
int n;
int c0, c1;
int score;
int d[N];
int sL[N];
int sR[N];


int crossMid(int least) {
    vector<PII> L, R;
    for(int i = n - 1; i >= 0; i--) {
        while(!L.empty() && sL[i] >= L.back().x) L.pop_back();
        L.pb(mp(sL[i], n - i));
    }

    for(int i = 0; i < n; i++) {
        while(!R.empty() && sR[i] >= R.back().x) R.pop_back();
        R.pb(mp(sR[i], i + 1));
    }

    int res = 0;
    for(int i = 0; i < L.size(); i++) if(L[i].x >= least) chmax(res, L[i].y);
    for(int i = 0; i < R.size(); i++) if(R[i].x >= least) chmax(res, R[i].y);
    int l = 0, r = (int) R.size() - 1;
    while(l < L.size() && r >= 0) {
        while(r >= 0 && L[l].x + R[r].x < least) r--;
        if(r >= 0) chmax(res, L[l].y + R[r].y);
        l++;

    }
    return res;
}


int p[N];
int rmax[N];

LL solve() {
    for(int i = 0; i < n; i++) p[i + 1] = sR[i];
    rmax[n] = p[n];
    for(int i = n - 1; i >= 0; i--) rmax[i] = max(rmax[i + 1], p[i]);
    int mx = 0;
    int l = 0;
    int r = 0;
    for(int i = 0; i < n; i++) {
        if(i != 0 && p[i] >= p[l]) continue;
        int rr = -1;
        while(r <= n && rmax[r] - p[i] >= 0) {
            rr = r - i;
            r++;
        }
        r--;
        int len = rr;
        if(mx <= len) {
            mx = len;
            l = i;
        }
    }
    return mx;
}

LL brute() {
    string S;
    for(int i = 0; i < K; i++) S += s;
    vector<int> pt(S.length() + 1, 0);
    LL res = 0;
    for(int i = 0; i < S.length(); i++) pt[i + 1] = pt[i] + d[i % n];
    int pi = -1, pj = -1;
    for(int i = 0; i < S.length(); i++)
        for(int j = i; j < S.length(); j++) {
            LL sc = pt[j + 1] - pt[i];
            if(sc >= 0 && chmax(res, (LL)(j - i + 1))) {
                pi = i, pj = j;
            }
        }
    return res;
}

int main() {
    cin >> K >> s;
    n = s.length();
    for(int i = 0; i < n; i++) {
        if(s[i] == '0') {
            c0++;
            d[i] = -2;
        } else {
            c1++;
            d[i] = 3;
        }
        score += d[i];
    }

    //P(score);
    LL res = 0;
    if(score >= 0) {
        res = (LL) n * K;
    } else {
        int tot = 0;
        {
            int mx = 0;
            for(int i = n - 1; i >= 0; i--) {
                sL[i] = sL[i + 1] + d[i];
                chmax(mx, sL[i]);
            }
            tot += mx;
        }
        {
            int mx = 0;
            for(int i = 0; i < n; i++) {
                if(i > 0) sR[i] = sR[i - 1] + d[i];
                else sR[i] = d[i];
                chmax(mx, sR[i]);
            }
            tot += mx;
        }

        if(K >= 2) {
            LL T = min(K - 2, tot / abs(score));
            res += n * T;
            //        P(res);
            res += crossMid(-score * T);
            chmax(res, solve());
        } else {
            res = solve();
        }
    }
    cout << res << endl;
    //P(brute());
    return 0;
}
```