zoukankan      html  css  js  c++  java
  • [Algorithms] Longest Common Substring

    The Longest Common Substring (LCS) problem is as follows:

    Given two strings s and t, find the length of the longest string r, which is a substring of both s and t.

    This problem is a classic application of Dynamic Programming. Let's define the sub-problem (state) P[i][j] to be the length of the longest substring ends at i of s and j of t. Then the state equations are

    1. P[i][j] = 0 if s[i] != t[j];
    2. P[i][j] = P[i - 1][j - 1] + 1 if s[i] == t[j].

    This algorithm gives the length of the longest common substring. If we want the substring itself, we simply find the largest P[i][j] and return s.substr(i - P[i][j] + 1, P[i][j]) or t.substr(j - P[i][j] + 1, P[i][j]).

    Then we have the following code.

     1 string longestCommonSubstring(string s, string t) {
     2     int m = s.length(), n = t.length();
     3     vector<vector<int> > dp(m, vector<int> (n, 0));
     4     int start = 0, len = 0;
     5     for (int i = 0; i < m; i++) {
     6         for (int j = 0; j < n; j++) {
     7             if (i == 0 || j == 0) dp[i][j] = (s[i] == t[j]);
     8             else dp[i][j] = (s[i] == t[j] ? dp[i - 1][j - 1] + 1: 0);
     9             if (dp[i][j] > len) {
    10                 len = dp[i][j];
    11                 start = i - len + 1;
    12             }
    13         }
    14     }
    15     return s.substr(start, len);
    16 }

    The above code costs O(m*n) time complexity and O(m*n) space complexity. In fact, it can be optimized to O(min(m, n)) space complexity. The observations is that each time we update dp[i][j], we only need dp[i - 1][j - 1], which is simply the value of the above grid before updates.

    Now we will have the following code.

     1 string longestCommonSubstringSpaceEfficient(string s, string t) {
     2     int m = s.length(), n = t.length();
     3     vector<int> cur(m, 0);
     4     int start = 0, len = 0, pre = 0;
     5     for (int j = 0; j < n; j++) {
     6         for (int i = 0; i < m; i++) {
     7             int temp = cur[i];
     8             cur[i] = (s[i] == t[j] ? pre + 1 : 0);
     9             if (cur[i] > len) {
    10                 len = cur[i];
    11                 start = i - len + 1;
    12             }
    13             pre = temp;
    14         }
    15     }
    16     return s.substr(start, len);
    17 }

    In fact, the code above is of O(m) space complexity. You may choose the small size for cur and repeat the same code using if..else.. to save more spaces :)

  • 相关阅读:
    VS 2008潜在强大的功能:提取EXE文件中的ICO等资源
    园友们注意:淘宝网上QQ会员 4钻 3元 等都为骗子行为
    Comet Async Process Request Handler
    WCF(Sender) to MSMQ to WCF(Receiver)
    ASP.NET Web Form GridView DetailsView Query Edit
    WCF NetTcp AsyncQueue Service
    Xml CDATA 序列化
    Sync Invoke Remoting Async Invoke
    .Net 4.0 Remoting ConcurrentQueue
    Socket Async Receive Data to LinkedList Buffer (telnet proxy server)
  • 原文地址:https://www.cnblogs.com/jcliBlogger/p/4574263.html
Copyright © 2011-2022 走看看