【问题】给定两个字符串A和B,长度分别为m和n,要求找出它们最长的公共子串,并返回其长度。例如:
A = "HelloWorld"
B = "loop"
则A与B的最长公共子串为 "lo",返回的长度为2。
【思路】最长公共子串的问题不同于最长公共子序列,由于子串的连续的,而子序列不一定连续。在上一个子序列中dp[i][j]是非减的,因此最后返回最大公共子序列时,返回的是dp[n][m]。而在最大子串问题中,dp[i][j]可能小于dp[i-1][j-1],因此需要一个res来保存更新最大值。
通俗考虑,在两个子串中寻找,假设a[i]==b[j]了,那么从i和j向后走,res会一直更新变大,一旦遇到不相等时,则dp[i][j]清零,寻找下一个重复的子串。因此其递推式为:
其中dp[i][0] = 0, dp[0][j] = 0;
class LongestSubstring { public: int findLongest(string A, int n, string B, int m) { if(n == 0 || m == 0) return 0; int rs = 0; int dp[n + 1][m + 1]; for(int i = 0 ; i <= n; i++)//初始状态 dp[i][0] = 0; for(int i = 0; i <= m; i++) dp[0][i] = 0; for(int i = 1; i <= n; i++) for(int j = 1; j<= m; j++) { if(A[i - 1] == B[j - 1]) { dp[i][j] = dp[i -1][j - 1] + 1; rs = max(rs,dp[i][j]);//每次更新记录最大值 } else//不相等的情况 dp[i][j] = 0; } return rs;//返回的结果为rs } };