Ticket #14969: trac_14969.patch

File trac_14969.patch, 3.0 KB (added by ncohen, 7 years ago)
  • sage/combinat/words/finite_word.py

    # HG changeset patch
    # User Nathann Cohen <nathann.cohen@gmail.com>
    # Date 1374746827 -7200
    #      Thu Jul 25 12:07:07 2013 +0200
    # Node ID 1bbb2f6416b3b032144ab1038a34b5396e106a27
    # Parent  4de3b579bf03a8f2c009d2e5e9e0768151d67823
    Longest Common subword
    
    diff --git a/sage/combinat/words/finite_word.py b/sage/combinat/words/finite_word.py
    a b  
    33023302            possible = xrange(1, n)
    33033303        return filter(self.has_period, possible)
    33043304
     3305    def longest_common_subword(self,other):
     3306        r"""
     3307        Returns a longest subword of ``self`` and ``other``.
     3308
     3309        For more information, see
     3310        :wikipedia:`Longest_common_subsequence_problem`.
     3311
     3312        INPUT:
     3313
     3314        - ``other`` -- a word
     3315
     3316        ALGORITHM:
     3317
     3318        For any indices `i,j'`, we compute the longest common subword ``lcs[i,j]`` of
     3319        `self[:i]` and `other[:j]`. This can be easily obtained as the maximum
     3320        of
     3321
     3322        - ``lcs[i-1,j]``
     3323
     3324        - ``lcs[i,j-1]``
     3325
     3326        - ``lcs[i-1,j-1]+1`` if ``self[i]==other[j]``
     3327
     3328        EXAMPLE::
     3329
     3330            sage: w1 = Word("1010101010101010101010101010101010101010")
     3331            sage: w2 = Word("0011001100110011001100110011001100110011")
     3332            sage: w1.longest_common_subword(w2)
     3333            word: 00110011001100110011010101010
     3334
     3335        TESTS::
     3336
     3337            sage: Word().longest_common_subword(Word())
     3338            word:
     3339
     3340        .. SEEALSO::
     3341
     3342            :meth:`is_subword_of`
     3343        """
     3344        from sage.combinat.words.word import Word
     3345        if len(self) == 0 or len(other) == 0:
     3346            return Word()
     3347
     3348        w2 = list(other)
     3349
     3350        # In order to avoid storing lcs[i,j] for each pair i,j of indices, we
     3351        # only store the lcs[i,j] for two consecutive values of i. At any step
     3352        # of the algorithm, lcs[i,j] is stored at lcs[0][j] and lcs[-1,j] is
     3353        # stored at lcs[1][j]
     3354        l1 = self[0]
     3355
     3356        # The weird +1 that follows exists to make sure that lcs[i,-1] returns
     3357        # the empty word
     3358        lcs = [[[] for i in range(len(w2)+1)] for j in range(2)]
     3359
     3360        for i,l1 in enumerate(self):
     3361            for j,l2 in enumerate(other):
     3362                lcs[0][j] = max(lcs[0][j-1],lcs[1][j],lcs[1][j-1] + ([l1] if l1==l2 else []),key=len)
     3363
     3364            # Maintaining the meaning of lcs for the next loop
     3365            lcs.pop(1)
     3366            lcs.insert(0,[[] for i in range(len(w2)+1)])
     3367
     3368        return Word(lcs[1][-2])
     3369
    33053370    def is_subword_of(self, other):
    33063371        r"""
    33073372        Returns True is self is a subword of other, and False otherwise.
    3308        
     3373
    33093374        EXAMPLES::
    33103375
    33113376            sage: Word().is_subword_of(Word('123'))
     
    33143379            True
    33153380            sage: Word('321').is_subword_of(Word('11122212112122133111222332'))
    33163381            False
     3382
     3383        .. SEEALSO::
     3384
     3385            :meth:`longest_common_subword`
     3386
    33173387        """
    33183388        its = iter(self)
    33193389        try: