Problem:
Score : 1000 points

Problem Statement

You are given a string S consisting of digits between 1 and 9, inclusive.
You will insert at most K commas (,) into this string to separate it into multiple numbers.

Your task is to minimize the maximum number among those produced by inserting commas. Find minimum possible such value.

Constraints

0 ≦ K < |S| ≦ 100,000

S consists of digits between 1 and 9, inclusive.

Partial Scores

In the test set worth 100 points, |S| ≦ 2.

In the test set worth another 100 points, |S| ≦ 16.

In the test set worth another 200 points, |S| ≦ 100.

In the test set worth another 200 points, |S| ≦ 2,000.

Input

The input is given from Standard Input in the following format:

K
S

Output

Print the minimum possible value.

Sample Input 1

2
15267315

Sample Output 1

315

When the string is separated into 152, 67 and 315, the maximum among these is 315, which is the minimum possible value.

Sample Input 2

0
12456174517653111

Sample Output 2

12456174517653111

12456174517653111 itself is the answer.

Sample Input 3

8
127356176351764127645176543176531763517635176531278461856198765816581726586715987216581

Sample Output 3

5317635176

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
static int k;
static string s;
static int n;
static int[] suffixNums;//a番目が何文字目からか
static int[] suffixArray;
static int stringLength;//最長の文字列の長さ
static int longCount;//最長の文字列の個数

	static void Main()
	{
		k = int.Parse(Console.ReadLine());
		s = Console.ReadLine();
    n = s.Length;
    suffixNums = new int[n];//a番目が何文字目からか
    suffixArray = SuffixArray(s);
    for(int i = 0; i < n; i++)
    {
      //Console.WriteLine(suffixArray[i]);
      suffixNums[suffixArray[i]] = i;
    }
    
    stringLength = (n+k)/(k+1);//最長の文字列の長さ
    longCount = n-(stringLength-1)*(k+1);//最長の文字列の個数
    //Console.WriteLine(stringLength+" "+longCount);

    int startNum = (int)Search(0,n-1,-1);
    //Console.WriteLine(n+" "+(n-stringLength)+" "+startNum);
    if(n % stringLength != 0)
    {
		  Console.WriteLine(s.Substring(suffixNums[startNum],stringLength));
    }else
    {
      
    }
	}

  static int[] SuffixArray(string s)
  {//a(0~n-1)文字目から最後の文字までを辞書順にした時の順番(0-index)をO(n(logn)^2)で返す
  //例えばacbなら{0,2,1}を返す
    int n = s.Length;
    int[] answers = new int[n];
    int[][] suffixes = new int[n][];
    for(int i = 0; i < n; i++)
    {
      suffixes[i] = new int[3];
      suffixes[i][0] = i;//初期位置
      suffixes[i][1] = s[i]-'1';//文字charをint(>=0)で辞書順に変換
      //Console.WriteLine(i+" "+suffixes[i][1]);
    }

    for(int i = 1; i < n; i*=2)
    {
      Array.Sort(suffixes, (a, b) => a[0].CompareTo(b[0]));
      for(int j = 0; j < n; j++)
      {
        if(j+i < n) suffixes[j][2] = suffixes[j+i][1];
        else suffixes[j][2] = -1;
        //Console.WriteLine(j+" "+suffixes[j][2]);
      }
      
      var sorted = suffixes.OrderBy(a => a[1]).ThenBy(a => a[2]).ToList();
      int numberMemo = 0;
      suffixes[sorted[0][0]][1] = numberMemo;
      for(int j = 1; j < n; j++)
      {
        if(sorted[j][1] != sorted[j-1][1] || sorted[j][2] != sorted[j-1][2])
        {
          numberMemo++;
        }
        
        suffixes[sorted[j][0]][1] = numberMemo;
        //Console.WriteLine(i+" "+j+" "+numberMemo);
      }
    }

    Array.Sort(suffixes, (a, b) => a[0].CompareTo(b[0]));
    for(int i = 0; i < n; i++)
    {
      answers[i] = suffixes[i][1];
    }  

    return answers;
  }

  static long Search(long min, long max, int MinorMax)//二分探索法で最小値-1最大値1を求める
  {
    while (true)
    {
      long mid = min + (max - min) / 2;
      if(MinorMax == 1)
      {
        if(Check(mid)) min = mid;//さらに大きくても成り立つかも
        else max = mid;
      }else
      {
        if(Check(mid)) max = mid;//さらに小さくても成り立つかも
        else min = mid;
      }

      if(max - min <= 1)
      {
        if(MinorMax == 1)
        {
          if(Check(max)) return max;//最大値で成り立つかの確認を優先
          else return min;
        }else
        {
          if(Check(min)) return min;//最小値で成り立つかの確認を優先
          else return max;
        }

      break;
      }  
    }
  }

  static bool Check(long testNum)
  {
    int lookingNum = 0;
    //Console.WriteLine(testNum+"b");
    testNum = suffixNums[testNum];
    //Console.WriteLine(testNum+"a");

    for(int i = 0; i < k+1; i++)
    {//分ける個数
    
      bool bigger = false;
      for(int j = 0; j < stringLength; j++)
      {
        if(lookingNum+j >= n || (int)testNum+j >= n) break;

        if(s[lookingNum+j] < s[(int)testNum+j]) break;
        else if(s[lookingNum+j] > s[(int)testNum+j])
        {
          bigger = true;
          break;
        }
      }
      lookingNum += stringLength-1;
      if(!bigger) lookingNum++;
    }

    //Console.WriteLine(lookingNum+" "+n);
    if(lookingNum >= n) return true;
    return false;
  }  
  
}