字母表中可以制作多少个N长度的字符串?需要一个有效的算法

时间:2017-01-03 17:44:26

标签: java algorithm math

问题是从字母表中可以制作多少长度为N的字符串。

条件是:

  1. 字母可以在字符串中重复
  2. 只有字母表中与字母相邻的字母才能在字符串中彼此相邻放置。例如,如果N = 4,则字符串可以是ABCD,ABAB,ABCB,WXYZ,XWXW等。它们不能是ABCE,CDEG,AAAA,因为字母表中只有相邻的字母可以放在一起。
  3. 我有N的答案:

    • 如果N = 3,答案是98
    • 如果N = 4,则回答为192
    • 如果N = 8,则答案是2896
    • 如果N = 15,则回答为342840
    • 如果N = 30,则回答为9841989098
    • 如果N = 40,则回答为9329564680878

    当N = 50时,我需要找到答案。我已经做出的算法正确地获取答案,直到30秒为止。然而,30后,我认为由于我的算法的递归性质,它继续运行,我没有得到答案。

    这是我的java代码:

    class Alphabet {
    
      public int n;
    
      public long counter = 0;
    
      public static void main(String[] args) {
        Alphabet a = new Alphabet(15);
        a.run();
      }
    
      public Alphabet(int n) {
        this.n = n;
      }
    
      public void run() {
    
        for (int i = 0; i < 13; i++) {
            this.attach(i, 1);
        }
    
        System.out.println(this.counter * 2);
      }
    
      public boolean attach(int letter, int length) {
    
        if (length == this.n) {
            this.counter++;
            return true;
        }
    
        if (letter == 0) {
            this.attach(1, length + 1);
            return true;
        }
    
        if (letter == 25) {
            this.attach(24, length + 1);
            return true;
        }
    
        this.attach(letter - 1, length + 1);
        this.attach(letter + 1, length + 1);
    
        return true;
      }
    }
    

    是否有更有效的方法来获得答案?

2 个答案:

答案 0 :(得分:4)

对于每个字母,计算以该字母结尾的长度为1的字符串数。对于所有字母,这是1。

如果您知道每个字母中以n字母字符串结尾的数字,那么很容易计算每个字母结尾的n + 1个字母字符串的数量。根据您的规则,这需要O(alphabet_size)时间。反复这样做,直到你达到n = N.然后只需将所有字母的计数加起来即可。

答案 1 :(得分:2)

如果x[i][j]是以字母j开头的i个字母的字符串数(从0开始编号),那么x[i][j]就会满足这些递归关系:

x[i][1] = 1
x[0][j] = x[1][j-1]
x[25][j] = x[24][j-1]
x[i][j] = x[i-1][j-1] + x[i+1][j-1]

这为您提供了一种解决问题的动态编程风格方法。 (这里是Python,因为它使算法更清晰,但是将它转换为Java没有根本的困难):

def strings(n):
    x = [1] * 26
    for _ in xrange(n-1):
        x = [x[1]] + [x[i-1] + x[i+1] for i in xrange(1, 25)] + [x[24]]
    return sum(x)

print strings(40)

这是一个O(n)(算术运算)解决方案。通过计算26x26矩阵的n次幂,可以在O(log n)算术运算中解决它。

A成为a[i][j]的矩阵ij = 0..25其中a[i][j] = 1如果|i-j]=1则为0。 / p>

然后:

x[][j] = A * (x[][j-1])

(这只是以矩阵形式写的递归关系)。

然后:

x[][n] = A^(n-1) (x[][1])

由于矩阵功率可以在O(log n)算术运算中计算(通过平方乘幂),因此可以在O(log n)时间内计算最终的x[][n]向量。这在实践中并没有多大帮助,因为数字变大了,但是如果你需要为某些K计算结果mod K,那么这是一个很好的方法。