时间:2010-07-26 18:06:50

标签: algorithm

5 个答案:

答案 0 :(得分:2)

请注意,为了尝试详尽的搜索(VB中的答案正在尝试一个简单的版本),您首先必须解决在保持字典顺序的同时生成所有可能的扩展的问题。只是ABC,扩展到AABC的所有权限,加上ABBC的所有权限,加上ABCC的所有权限,即3 * 4!而不仅仅是AABC。如果您只是连接AABC和AABD,它将只覆盖4个中的4个! AABC的烫发甚至是偶然的。只是这种扩展会给你带来指数级的复杂性 - 游戏结束。另外,您需要保持所有解释与集合之间的关联(集合成为标签)。

你最好的选择是使用一个已知的高效De Bruijn构造函数,并试着看看你是否可以将你的集合等价放在那里。看看

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.14.674&rep=rep1&type=pdf

http://www.dim.uchile.cl/~emoreno/publicaciones/FINALES/copyrighted/IPL05-De_Bruijn_sequences_and_De_Bruijn_graphs_for_a_general_language.pdf

开始。

如果你知道图形,另一个可行的选择是从De Bruijn图开始,并将你的集等价表示为图重写。第二篇论文是De Bruijn图分区。

顺便说一句,尝试VB答案仅针对A,B,AB(至少扩展很小) - 它将使AABBAB构建ABBA或ABBAB(或投入一种不错的语言),这两者都是错误的。你甚至可以通过检查前2次传球来证明它总是会错过第一次词汇扩展(这就是AAB,AAAB等)(因为(N-1)xA + B,所以它总是会错过NxA的第二次A) string({AB}的第一次扩展)。

哦,如果我们能确定一个最佳解决方案应该具有的每个字母的数量(不要看B(5,2)它太容易和规则:-)随机serch是可行的 - 你生成候选人可证明的特征(如AAAA,BBBB ......存在并且没有触及并且具有n1 As,n2 Bs ......)和随机排列然后测试它们是否是解决方案(在这种情况下检查比穷举搜索快得多)。

答案 1 :(得分:1)

很酷的问题。只是一个草稿/伪造的算法:

dim STR-A as string = getall(ABCDEFGHIJKL) 
//custom function to generate concat list of all 793 4-char combos.
//should be listed side-by-side to form 3172 character-long string.
//different ordering may ultimately produce different results.
//brute-forcing all orders of combos is too much work (793! is a big #).
//need to determine how to find optimal ordering, for this particular
//approach below.
dim STR-B as string = "" // to hold the string you're searching for  
dim STR-C as string = "" // to hold the sub-string you are searching in  
dim STR-A-NEW as string = "" //variable to hold your new string
dim MATCH as boolean = false //variable to hold matching status

while len(STR-A) > 0 
//check each character in STR-A, which will be shorted by 1 char on each
//pass.
  MATCH = false
  STR-B = left(STR-A, 4)
  STR-B = reduce(STR-B) 
  //reduce(str) is a custom re-usable function to sort & remove duplicates

  for i as integer = 1 to len((STR-A) - 1)
    STR-C = substr(STR-A, i, 4) 
    //gives you the 4-character sequence beginning at position i
    STR-C = reduce(STR-C)
    IF STR-B = STR-C Then
       MATCH = true
       exit for 
       //as long as there is even one match, you can throw-away the first 
       //letter
    END IF
    i = i+1
  next


  IF match = false then 
  //if you didn't find a match, then the first letter should be saved
     STR-A-NEW += LEFT(STR-B, 1)
  END IF

  MATCH = false //re-init MATCH
  STR-A = RIGHT(STR-A, LEN(STR-A) - 1) //re-init STR_A
wend

无论如何 - 这可能会有问题,你需要编写另一个函数来解析你的结果字符串(STR-A-NEW)来证明这是一个可行的答案......

答案 2 :(得分:0)

我一直在考虑这个,我正在草拟解决方案。

让我们将一个四个符号的字符串称为 word ,我们将写出 S(w)来表示单词 w

每个单词 abcd 都有“后续”单词 bcde 其中 a,...,e 都是符号。

succ(w)成为 w 的后续单词 v 的集合,以便 S(w)! = S(v) succ(w)是一组后继词,如果 w 在解决方案中,则可以从 w 中的第一个符号开始。

对于最多四个基数的每个非空符号 s ,让单词成为单词 w 的集合这样 S(w)= s 。对于每个这样的 s ,任何解决方案必须在 words(s)中只包含一个单词。

现在我们可以进行合理的搜索。基本思路是这样的:假设我们正在探索以 w 结尾的搜索路径。后续单词必须是 succ(w)中的非排除单词。如果搜索路径包含某些单词 w ,则单词 v 将被排除,以便 v in words(S(w))

你可以稍微狡猾:如果我们跟踪可能的“前任”单词到集合 s (即单词 w 与后继 v < / em>这样 v in words(s))并且达到 s 的每个前任被排除在外的点,然后我们知道我们已经走到了死胡同,因为我们永远无法从当前搜索路径的任何扩展名获取 s

周末之后的代码,运气不错......

答案 3 :(得分:0)

这是我的建议。我会事先承认这是一场表演和记忆困难。

这可能有点矫枉过正,但有一个类我们称之为UniqueCombination这将包含一个唯一的1-4 char减少的输入集合组合(即A,AB,ABC,...)这也将包含一个可能的组合列表(AB {AABB,ABAB,BBAA,...})这将需要一种方法来确定任何可能的组合是否与另一个UniqueCombination的任何可能组合重叠三个字符。还需要一个带字符串的覆盖。

然后我们从字符串“AAAA”开始,然后我们找到与该字符串重叠的所有UniqueCombinations。然后我们找到那些可能的匹配重叠的uniqueCombinations数量。 (我们现在可以很聪明地存储这个数字。)然后我们选择具有大于0的最小重叠数的那个。首先使用具有最少匹配的那个。

然后我们找到所选UniqueCombination的特定组合并将其添加到最终字符串。从列表中删除此UniqueCombination,然后我们找到当前字符串的重叠。冲洗并重复。 (我们可以很聪明,在搜索重叠的后续运行中,我们可以删除最终字符串中包含的任何未减少的组合。)

那是我的计划,我将在本周末处理代码。虽然这并不能保证最后4个字符是同一个字母的4个字符(它可能实际上是试图避免这个但我也会考虑这个。)

答案 4 :(得分:0)

如果存在非指数解决方案,则可能需要根据较小尺寸问题的递归“增长”来制定,即从B(N-1)构建B(N,k), k-1)或B(N-1,k)或B(N,k-1)。

B(5,2)的系统构造 - 当时只有一步:-)它必然会变得更加复杂[卡代表基数,{AB}有卡= 2,我也称它们为2 s,3-s等]注意,2-s和3-s将是k-1和k后者(我希望)。

  1. 初始。从k-1结果开始,为单例注入符号 (独特的扩展空交叉口):
    • ABCDE - &gt; AABBCCDDEE
  2. mark used card = 2套:AB,BC,CD,DE
  3. 重写。表格卡= 3套,将符号注入标记卡= 2。 第一次可行的词典扩展火灾(可能需要回溯k> 2)
    • 可以使用已标记的2-s,因为它们都将被替换
    • 但可能需要为更高的k
    • 执行验证通过
    • AB-> ACB,BC-> BCD,CD-> CED,DE-> DAE ==&gt; AACBBDCCEDDAEEB
  4. 标记/验证使用2s
    • 通常在施工期间保持标记/取消标记,但也要保持旧的 标记列表
    • 如果在#3 中有回溯,
    • 标记/取消标记可能会变得昂贵
    • 未使用:AB,BE
  5. 对于更高的k,可能需要几次递归重写传递
    • 可能将新集合划分为类
  6. 结束:未使用的2-s应该在边缘重叠(这就是为什么它是循环的)      ABE - B可以开始或者:和AACBBDCCEDDAEEB
  7. 注意:从B(N-1,k)到B(N,k)的步骤可能需要注入伪符号,如加倍或三重A

    B(5,2) - &gt; B(5,3) - B(5,4)

    1. 初始。相同: - ABCDE - &gt; AAACBBBDCCCEDDDAEEEB
    2. 没有使用标记3套,因为它们都将被彻底改变
    3. 重写。
      1. 选择系统插入位置
        • AAA_CBBB_DCCC_EDDD_AEEE_B
      2. 标记由此发布的所有2-s:AC,AD,BD,BE,CE
      3. 使用标记的2-s来决定插入的符号 - 总的规律性:
        • AxCB D - &gt; ADCB
        • BxDC E - &gt; BEDC
        • CxED A - &gt; CAED
        • DxAE B =&gt; DBAE
        • ExBA C - &gt;电子商务工商联盟
    4. 确认3-s全部使用(标记插入的符号只是为了好玩)
      • AAA [d] CBBB [E] DCCC [A] EDDD [B] AEEE [C]乙
    5. 注意:系统选择插入点是否确定性地决定了插入(只有AD可以适合1,AC会产生重复的2组(AAC,ACC))

      注意:B(6,2)和B(6,3)不会那么好,因为2-s的数量将超过1-s的2倍。这很重要,因为2-s自然地位于1-s的侧面,如CBBBE,问题是当你用完1-s时如何放置它们。

      • B(5,3)是如此对称,只重复#1产生B(5.4):
        • AAAADCBBBBEDCCCCAEDDDDBAEEEECB