6276. 统计同位异构字符串数目

2022/12/25 leetcode 共 1471 字,约 5 分钟

title

problem link

给你一个字符串 s ,它包含一个或者多个单词。单词之间用单个空格 ' ' 隔开。

如果字符串 t 中第 i 个单词是 s 中第 i 个单词的一个 排列 ,那么我们称字符串 t 是字符串 s 的同位异构字符串。

  • 比方说,"acb dfe" 是 "abc def" 的同位异构字符串,但是 "def cab" 和 "adc bef" 不是。

请你返回 s 的同位异构字符串的数目,由于答案可能很大,请你将它对 109 + 7 取余 后返回。

示例 1:

输入:s = "too hot"
输出:18
解释:输入字符串的一些同位异构字符串为 "too hot" ,"oot hot" ,"oto toh" ,"too toh" 以及 "too oht" 。

示例 2:

输入:s = "aa"
输出:1
解释:输入字符串只有一个同位异构字符串。

提示:

  • 1 <= s.length <= 105
  • s 只包含小写英文字母和空格 ' ' 。
  • 相邻单词之间由单个空格隔开。

solution

方法1: 大数阶乘除法,要用费马小定理。

方法2: 用comb换种思路,原来是阶乘相除,可以通过comb相乘,此时无除法。

MOD = 10 ** 9 + 7
class BigIntDivide:
    def mod_inverse(i):
        # 调用取模的乘幂运算, pow复杂度是log(exp)即log(MOD)
        return pow(i, MOD - 2, MOD)

    def divide_mod(a, b):
        '''
        计算(a/b) % MOD, 除法变乘法,前提是b和MOD互为质数
        '''
        # 如果有多个b,比如a/b1/b2, 那就可以递归。a*mod_inverse(b1) % mod * mod_inverse(b2) % mod这样
        return a * BigIntDivide.mod_inverse(b) % MOD

    def divide_mods(a, b=[]):
        '''
        计算a /(b1*b2*b3) % MOD等形式,前提是b和MOD互为质数
        '''
        r = a % MOD
        for i, v in enumerate(b):
            r *= BigIntDivide.mod_inverse(v)
            r %= MOD
        return r

class Math1:

    import functools
    @functools.lru_cache(None)
    def factorial_mod_cache(n):
        if n == 0 or n == 1:
            return 1
        return Math1.factorial_mod_cache(n - 1) * n % MOD        
class Solution:
    def countAnagrams(self, s: str) -> int:
        d = s.split(' ')

        factorial_mod = Math1.factorial_mod_cache

        def calcu(x):
            import collections
            counter = collections.Counter(x)
            n = len(x)
            return BigIntDivide.divide_mods(factorial_mod(n), [factorial_mod(v) for v in counter.values()])

        # print(calcu("too"))

        ans = 1
        for v in d:
            ans *= calcu(v)
            ans %= MOD
        return ans % MOD

方法2 参考

MOD = 10 ** 9 + 7


class Solution:
    def countAnagrams(self, s: str) -> int:
        ans = 1
        for word in s.split():
            n = len(word)
            for v in Counter(word).values():
                ans *= comb(n, v)
                ans %= MOD
                n -= v
        return ans

Search

    Table of Contents