#include <bits/stdc++.h>   #pragma comment(linker,  /STACK:16777216 )   using namespace std;   template <typename T, int N>   struct SuffixArray {     T data[N + 1];     int result[N + 1], bucket[N + 1], count[N + 1], lcp[N + 1], n;     pair<T, int> tmp[N + 1];     SuffixArray() : n(0) {}     SuffixArray(T *source, int length) {       memcpy(data, source, length * sizeof(T));       n = length;     }     inline void reset(int length) { n = length; }     inline void reset(T *source, int length) {       memcpy(data, source, length * sizeof(T));       n = length;     }     void build(bool cyclic = false, bool char_speedup = false) {       bool clean_needed = false;       if (!cyclic) {         clean_needed = true;         data[n++] |= (T)1 << (8 * sizeof(T) - 1);       }       for (int i = 0; i < n; ++i) result[i] = i;       int max_group = 0;       for (int current_length = 1; current_length < n * 2; current_length *= 2) {         if (current_length == 1) {           if (!char_speedup) {             for (int i = 0; i < n; ++i) tmp[i] = make_pair(data[i], i);             sort(tmp, tmp + n);             for (int i = 0; i < n; ++i) result[i] = tmp[i].second;             for (int i = 0; i < n; ++i) bucket[i] = data[i];           } else {             int char_count[256];             memset(char_count, 0, 256 * sizeof(int));             int minimal_value = 0;             if (clean_needed)               minimal_value = data[n - 1];             else               minimal_value = *min_element(data, data + n);             for (int i = 0; i < n; ++i) ++char_count[data[i] - minimal_value];             for (int i = 1; i < 256; ++i) char_count[i] += char_count[i - 1];             for (int i = n - 1; i >= 0; --i)               lcp[--char_count[data[i] - minimal_value]] = i;             memcpy(result, lcp, n * sizeof(int));             for (int i = 0; i < n; ++i) bucket[i] = data[i];           }           int total_count = 0;           for (int i = 0; i < n;) {             int j = i;             int current_bucket = bucket[result[i]];             while (j < n && bucket[result[j]] == current_bucket) ++j;             for (int z = i; z < j; ++z) bucket[result[z]] = total_count;             ++total_count;             i = j;           }           max_group = total_count;           continue;         }         int prev_length = current_length / 2;         for (int i = 0; i < n; ++i) result[i] = (result[i] - prev_length + n) % n;         memset(count, 0, max_group * sizeof(int));         for (int i = 0; i < n; ++i) ++count[bucket[i]];         for (int i = 1; i < max_group; ++i) count[i] += count[i - 1];         for (int i = n - 1; i >= 0; --i)           lcp[--count[bucket[result[i]]]] = result[i];         memcpy(result, lcp, n * sizeof(int));         int total_count = 0;         for (int i = 0; i < n;) {           int j = i;           int current_bucket_first = bucket[result[i]],               current_bucket_second = bucket[(result[i] + prev_length) % n];           while (j < n && bucket[result[j]] == current_bucket_first &&                  bucket[(result[j] + prev_length) % n] == current_bucket_second)             ++j;           for (int z = i; z < j; ++z) lcp[result[z]] = total_count;           ++total_count;           i = j;         }         max_group = total_count;         memcpy(bucket, lcp, n * sizeof(int));       }       if (clean_needed) {         --n;         for (int i = 0; i < n; ++i) result[i] = result[i + 1];       }     }     void buildLCP() {       for (int i = 0; i < n; ++i) count[result[i]] = i;       int h = 0;       lcp[0] = 0;       for (int i = 0; i < n; ++i) {         if (count[i]) {           while (data[i + h] == data[result[count[i] - 1] + h]) ++h;           lcp[count[i]] = h--;           if (h < 0) h = 0;         }       }     }   };   int a, b, c, d, i, j, n, m, k;   SuffixArray<char, 100002> q;   char str[200202], ans[200002];   long long cs[200002];   inline long long sum(int l, int r) {     if (!l)       return cs[r];     else       return cs[r] - cs[l - 1];   }   int main() {     scanf( %s , str);     scanf( %d , &k);     n = (int)strlen(str);     if (k > (long long)n * (n + 1) / 2) {       puts( No such line. );       exit(0);     }     --k;     q.reset(str, n);     q.build(false, true);     a = 0;     b = n;     for (int _n((n)-1), i(0); i <= _n; i++) {       cs[i] = n - q.result[i];       if (i) cs[i] += cs[i - 1];     }     for (int _n((1000000000) - 1), len(0); len <= _n; len++) {       if (k < 0 && len) {         ans[len] = 0;         puts(ans);         exit(0);       }       for (int _n((26) - 1), i(0); i <= _n; i++) {         char ch =  a  + i;         int l = a, r = b;         while (r - l > 1) {           int xx = (r + l) / 2;           if (str[q.result[xx] + len] > ch)             r = xx;           else             l = xx;         }         int right = l;         if (str[q.result[right] + len] > ch) --right;         l = a, r = b;         while (r - l > 1) {           int xx = (r + l) / 2;           if (str[q.result[xx] + len] >= ch)             r = xx;           else             l = xx;         }         int left = l;         if (str[q.result[left] + len] < ch) ++left;         if (left > right) continue;         long long cur = sum(left, right) - (long long)len * (right - left + 1);         if (cur <= k)           k -= cur;         else {           ans[len] = ch;           a = left;           b = right + 1;           k -= b - a;           break;         }       }     }   }