import
java.util.Arrays;
class
Suffix {
int
index;
int
[] rank =
new
int
[
2
];
}
public
class
Main {
static
int
[] buildSuffixArray(String txt,
int
n) {
Suffix[] suffixes =
new
Suffix[n];
for
(
int
i =
0
; i < n; i++) {
suffixes[i] =
new
Suffix();
}
for
(
int
i =
0
; i < n; i++) {
suffixes[i].index = i;
suffixes[i].rank[
0
] = txt.charAt(i) -
'a'
;
suffixes[i].rank[
1
] = ((i +
1
) < n) ? txt.charAt(i +
1
) -
'a'
: -
1
;
}
Arrays.sort(suffixes, (a, b) -> {
if
(a.rank[
0
] != b.rank[
0
]) {
return
a.rank[
0
] - b.rank[
0
];
}
else
{
return
a.rank[
1
] - b.rank[
1
];
}
});
int
[] ind =
new
int
[n];
int
k =
4
;
while
(k <
2
* n) {
k *=
2
;
int
rank =
0
;
int
prev_rank = suffixes[
0
].rank[
0
];
suffixes[
0
].rank[
0
] = rank;
ind[suffixes[
0
].index] =
0
;
for
(
int
i =
1
; i < n; i++) {
if
(suffixes[i].rank[
0
] == prev_rank && suffixes[i].rank[
1
] == suffixes[i -
1
].rank[
1
]) {
prev_rank = suffixes[i].rank[
0
];
suffixes[i].rank[
0
] = rank;
}
else
{
prev_rank = suffixes[i].rank[
0
];
rank++;
suffixes[i].rank[
0
] = rank;
}
ind[suffixes[i].index] = i;
}
for
(
int
i =
0
; i < n; i++) {
int
nextindex = suffixes[i].index + k /
2
;
suffixes[i].rank[
1
] = (nextindex < n) ? suffixes[ind[nextindex]].rank[
0
] : -
1
;
}
Arrays.sort(suffixes, (a, b) -> {
if
(a.rank[
0
] != b.rank[
0
]) {
return
a.rank[
0
] - b.rank[
0
];
}
else
{
return
a.rank[
1
] - b.rank[
1
];
}
});
}
int
[] suffixArr =
new
int
[n];
for
(
int
i =
0
; i < n; i++) {
suffixArr[i] = suffixes[i].index;
}
return
suffixArr;
}
static
int
[] kasai(String txt,
int
[] suffixArr) {
int
n = suffixArr.length;
int
[] lcp =
new
int
[n];
int
[] invSuff =
new
int
[n];
for
(
int
i =
0
; i < n; i++) {
invSuff[suffixArr[i]] = i;
}
int
k =
0
;
for
(
int
i =
0
; i < n; i++) {
if
(invSuff[i] == n -
1
) {
k =
0
;
continue
;
}
int
j = suffixArr[invSuff[i] +
1
];
while
(i + k < n && j + k < n && txt.charAt(i + k) == txt.charAt(j + k)) {
k++;
}
lcp[invSuff[i]] = k;
if
(k >
0
) {
k--;
}
}
return
lcp;
}
static
int
sumOfFirstN(
int
N) {
return
(N * (N +
1
)) /
2
;
}
static
char
printKthCharInConcatSubstring(String string,
int
K) {
int
n = string.length();
int
[] suffixArr = buildSuffixArray(string, n);
int
[] lcp = kasai(string, suffixArr);
for
(
int
i =
0
; i < lcp.length; i++) {
int
charToSkip = (sumOfFirstN(n - suffixArr[i]) - sumOfFirstN(lcp[i]));
if
(K <= charToSkip) {
for
(
int
j = lcp[i] +
1
; j <= (n - suffixArr[i]); j++) {
int
curSubstringLen = j;
if
(K <= curSubstringLen) {
return
string.charAt(suffixArr[i] + K -
1
);
}
else
{
K -= curSubstringLen;
}
}
break
;
}
else
{
K -= charToSkip;
}
}
return
' '
;
}
public
static
void
main(String[] args) {
String string =
"banana"
;
int
K =
10
;
System.out.println(printKthCharInConcatSubstring(string, K));
}
}