Problem:
String in String

Problem

文字列SとQ個のクエリが与えられる。

i番目のクエリ(0 ≤ i ≤ Q-1)には閉区間[li,ri]と文字列Miが与えられる。
Sのli文字目からri文字目までの部分文字列の中に文字列Miはいくつ存在するか出力せよ。

Input

入力は以下の形式で与えられる。

S Q
l0 r0 M0
l1 r1 M1
.
.
.
lQ−1 rQ−1 MQ−1

1行目に文字列Sとクエリの数Qが空白区切りで与えられる。

続くQ行に整数li, ri, Miが空白区切りで与えられる。

Constraints

1 ≤| S | ≤ 100000

1 ≤ Q ≤ 100000

1 ≤ | Mi | ≤ 100000 (0 ≤ i ≤ Q-1)

0 ≤ li ≤ ri < | S | (0 ≤ i ≤ Q-1)

文字はすべて英小文字である

文字列Mの合計文字数は2000000を越えない

Output

出力はQ行からなる。各クエリに対する答えを順番に1行に出力せよ。

Sample Input 1

rupcrupc 5
0 3 rupc
0 7 rupc
2 7 ru
2 7 pc
1 5 u

Sample Output 1

1
2
1
2
2

Sample Input 2

abatagaadbura 8
0 6 a
6 12 a
0 6 aa
0 3 a
3 5 a
5 9 a
1 8 b
1 12 b

Sample Output 2

4
3
0
2
1
2
1
2

Sample Input 3

aaaaaaaaaa 5
0 9 aaa
0 9 aa
5 9 aaaa
2 8 aa
1 2 a

Sample Output 3

8
9
2
6
2

Solution in Kotlin (judge verdict: Accepted)

import java.util.*
import kotlin.Comparator

fun main(args: Array<String>) {
    //https://onlinejudge.u-aizu.ac.jp/challenges/sources/UOA/UAPC/1585?year=2016
    val (str, q) = readLine()!!.trim().split(' ')
    val suffix = makeSuffixArray(str)
    val queries = Array(q.toInt()){
        val (l, r, s) = readLine()!!.trim().split(' ')
        Query(it, l.toInt(), r.toInt() - s.length + 1, s)
    }
    val bit = Bit(str.length)
    val left = PriorityQueue<Query>(compareBy(Query::left)).also{it.addAll(queries.filter{it.right >= 0})}
    val right = PriorityQueue<Query>(compareBy(Query::right))
    val rank = IntArray(str.length){0}.also{array -> array.indices.forEach { array[suffix[it]] = it }}
    val result = IntArray(queries.size){0}
    for ((index, pos) in rank.withIndex()) {
        while (left.isNotEmpty() && left.first().left == index) {
            val query = left.poll()
            val l = suffix.firstTrue { startIndex ->
                StringSlice(query.pattern) <= StringSlice(str, startIndex, startIndex + query.pattern.length)
            }
            val r = suffix.firstTrue { startIndex ->
                StringSlice(query.pattern) < StringSlice(str, startIndex, startIndex + query.pattern.length)
            }
            val count = bit.get(r - 1) - bit.get(l - 1)
            result[query.id] -= count
            right.add(query)
        }
        bit.add(pos, 1)
        while (right.isNotEmpty() && right.first().right <= index) {
            val query = right.poll()
            val l = suffix.firstTrue { startIndex ->
                StringSlice(query.pattern) <= StringSlice(str, startIndex, startIndex + query.pattern.length)
            }
            val r = suffix.firstTrue { startIndex ->
                StringSlice(query.pattern) < StringSlice(str, startIndex, startIndex + query.pattern.length)
            }
            val count = bit.get(r - 1) - bit.get(l - 1)
            result[query.id] += count
        }
    }
    println(result.joinToString("\n"))
}
data class Query(val id: Int, val left: Int, val right: Int, val pattern: String)
class StringSlice(val str: String, val from: Int, val until: Int): Comparable<StringSlice> {
    constructor(str: String, startIndex: Int): this(str, startIndex, str.length)
    constructor(str: String):this(str, 0, str.length)
    override fun compareTo(other: StringSlice): Int {
        for (i in 0 until minOf(size, other.size)) {
            val res = this[i].compareTo(other[i])
            when(res) {
                0 -> Unit
                else -> return res
            }
        }
        return size.compareTo(other.size)
    }
    operator fun get(index: Int): Char = str[from + index]
    val size: Int = minOf(until, str.length) - from
    val indices: IntRange = 0 until size
    override fun toString(): String {
        return indices.joinToString(""){"${this[it]}"}
    }
}
inline fun IntArray.firstTrue(predicate: (value: Int) -> Boolean): Int {
    var min = 0
    var max = size
    while (min < max) {
        val mid = (min + max) shr 1
        if (!predicate(this[mid])) {
            min = mid + 1
        }else {
            max = mid
        }
    }
    return max
}
class Bit(val size: Int) {
    private val array = IntArray(size){0}
    fun get(position: Int): Int {
        return if (position in array.indices) array[position] + get(position - (position.inv() and (position + 1)))
            else 0
    }
    tailrec fun add(position: Int, value: Int): Unit {
        if (position !in array.indices) return
        array[position] += value
        add(position + (position.inv() and (position + 1)), value)
    }
}
fun makeSuffixArray(str: String): IntArray {
    val indices = str.indices.toMutableList().also{it.sortBy(str::get)}
    val rank = IntArray(str.length shl 1){0}.also{array ->
        array[indices[0]] = 1
        for (i in 1 until indices.size) {
            array[indices[i]] = if (str[indices[i]] == str[indices[i - 1]]) {
                 array[indices[i - 1]]
            }else {
                array[indices[i - 1]] + 1
            }
        }
    }
    val tempRank = IntArray(str.length){0}
    var len = 1
    while (len <= str.length) {
        indices.sortWith(Comparator { o1, o2 ->
            val res = rank[o1].compareTo(rank[o2])
            when(res) {
                0 -> rank[o1 + len].compareTo(rank[o2 + len])
                else -> res
            }
        })

        tempRank[indices[0]] = 1
        for (i in 1 until indices.size) {
            tempRank[indices[i]] = if (rank[indices[i]] == rank[indices[i - 1]] && rank[indices[i] + len] == rank[indices[i - 1] + len]) {
                tempRank[indices[i - 1]]
            }else {
                tempRank[indices[i - 1]] + 1
            }
        }
        for (i in tempRank.indices) rank[i] = tempRank[i]
        len = len shl 1
    }
    return indices.toIntArray()
}