【问题标题】:Find total number of palindrome of size N using K letters使用 K 个字母查找大小为 N 的回文的总数
【发布时间】:2019-05-05 13:44:39
【问题描述】:

使用 K 个字母求长度为 N 的回文的总数,使得长度为 2 到 N-1 的任何前缀都不是回文。

试过K*((K-1)^(Math.ceil((N-2)/2))) 第一名可以装K个字母。第二个可以K-1,除了第一名。第三个也一样。 由于我们需要用字母填充的地方有一半将遵循相同的方式使其成为回文。但它不是正确的解决方案。

【问题讨论】:

  • $K$ 字母必须不同吗?你怎么知道你的解决方案不正确?它有什么不正确的?您标记了动态编程,但您的解决方案不涉及 DP——您有理由认为它应该这样做吗?
  • 是的,K 字母是不同的,但您可以在同一个字符串中多次使用它们。它可能需要 DP 来解决这个问题,但不确定。此解决方案不包含所有可能的此类回文字符串。

标签: algorithm permutation dynamic-programming palindrome discrete-mathematics


【解决方案1】:

表示M = \ceil{N / 2}。该公式取决于一个简单的观察,即如果一个长度为N 的回文具有一个长度小于2 的非平凡回文前缀(即长度至少为2),那么它具有一个长度为大多数M

如果我们用f(n) 表示长度为n回文数(那些在2n - 1 之间没有长度回文前缀的回文数),我们可以计算@987654330 @通过减去bad回文数得到回文总数,即K^M。通过上面的观察,每个坏回文在2M(包括)之间都有一个长度为L最小非平凡回文前缀,它必须是一个好的回文。每个L都有f(L)这样的前缀,并且它们中的任何一个都可以以K^{M - L}的方式扩展到长度为N的回文,所以

f(2) = K
f(N) = K^M - \sum_{L=2}^{M} K^{M - L}f(L)

【讨论】:

    【解决方案2】:

    我编写了一个 Python 脚本来检查 Łukasz's answer 中的小值 NK

    游乐场:https://ideone.com/7Nk41y

    import functools
    import itertools
    import string
    
    
    @functools.lru_cache()
    def f(N, K):
        if N == 2:
            return K
        M = (N + 1)//2
        return K**M - sum(K**(M - L) * f(L, K) for L in range(2, M+1))
    
    
    def is_palindrome(s):
        return s[:(len(s) + 1)//2] == s[len(s)//2:][::-1]
    
    
    def brutal_f(N, K):
        alphabet = string.ascii_lowercase[:K]
        ret = 0
        for t in itertools.product(alphabet, repeat=N):
            s = "".join(t)
            if is_palindrome(s) and not any(is_palindrome(s[:i]) for i in range(2, N)):
                ret += 1
        return ret
    
    
    print(all(
            f(N, K) == brutal_f(N, K)
            for N in range(12)
            for K in range(4)
        ))
    

    【讨论】:

      猜你喜欢
      • 2015-09-19
      • 2015-08-14
      • 2018-09-06
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-02
      • 1970-01-01
      相关资源
      最近更新 更多