Maximum Palindromes

  • + 0 comments

    My answer with Typescript, Has runtime error with few very very large test 100.000+ that idk where cause 50kb limit test

    function answerQuery(l: number, r: number): number {
        let memo_factorial = new Map<bigint, bigint>([[0n, 1n], [1n, 1n]])
        function factorial(n: bigint): bigint {
            if (!memo_factorial.has(n)) {
                let i_ = Array.from(memo_factorial.keys()).pop() || 1n;
                let r_ = memo_factorial.get(i_)!
                for (let i = i_ + 1n; i <= n; i++) {
                    r_ *= i
                    memo_factorial.set(i, r_)
                }
            }
            return memo_factorial.get(n)!;
        }
    
        // 0. get the substring from [l] and [r], get [frequency]
        const s = str.substring(l - 1, r)
        const frequency = new Map<string, number>()
        for (let c of s) frequency.set(c, (frequency.get(c) || 0) + 1)
    
        /**
         *              factorial(p_alls)
         *          m * ------------------------------- (modulo 10^9 + 7)
         *              factorial(p*...)
         * 
         * with:
         *  + [m]: numbers of character that odd, mean it can be middle
         *  + [p]: colection of character that can be appears in 2 side of palidrome
         */
    
        /**
         * Update 1: Number exceeded Number.MAX_SAFE_INTEGER -> using BigInt
         * Update 2: Maximum call stack exceeded -> changes [factorial] to use for...loop insteads of recursive
         * Update 3: Some test timeout -> try memo
         * Update 4: Some test with 100.000 has runtime error, idk where cause 50kb limit custom test
         */
        
        // 1. calculate prepare for formular
        let p_alls = factorial(BigInt(Array.from(frequency.values()).reduce((_, v) => _ + Math.floor(v / 2), 0)))
        let p_each = Array.from(frequency.values()).reduce((_, v) => _ * factorial(BigInt(Math.floor(v / 2))), 1n)
        let m = BigInt(Math.max(Array.from(frequency.values()).reduce((_, v) => _ + v % 2, 0), 1))
        
        // 2. apply formular
        return Number((m * p_alls / p_each) % BigInt(10 ** 9 + 7))
    }