# Longest Common Substring (Java)

In computer science, the longest common substring problem is to find the longest string that is a substring of two or more strings.

Analysis

Given two strings a and b, let dp[i][j] be the length of the common substring ending at a[i] and b[j]. The dp table looks like the following given a="abc" and b="abcd". Java Solution

```public static int getLongestCommonSubstring(String a, String b){ int m = a.length(); int n = b.length();   int max = 0;   int[][] dp = new int[m][n];   for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ if(a.charAt(i) == b.charAt(j)){ if(i==0 || j==0){ dp[i][j]=1; }else{ dp[i][j] = dp[i-1][j-1]+1; }   if(max < dp[i][j]) max = dp[i][j]; }   } }   return max; }```

This is a similar problem like longest common subsequence. The difference of the solution is that for this problem when a[i]!=b[j], dp[i][j] are all zeros by default. However, in the longest common subsequence problem, dp[i][j] values are carried from the previous values, i.e., dp[i-1][j] and dp[i][j-1].

Category >> Algorithms
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• Coding freek

There are four different ways to solve this problem –

``` // Method1()- recursive solution(Top- down approach) // time complexity - O(3^(m+n)) // space complexity - O(m+n) public static int LCSubStrM1(char[] X, char[] Y, int m, int n, int lcsCount) { if (m <= 0 || n <= 0) return lcsCount;```

``` int lcsCount1=lcsCount; if (X[m - 1] == Y[n - 1]) lcsCount1 = LCSubStrM1(X, Y, m - 1, n - 1, lcsCount + 1); int lcsCount2 = LCSubStrM1(X, Y, m, n - 1, 0); int lcsCount3 = LCSubStrM1(X, Y, m - 1, n, 0); return Math.max(lcsCount1, Math.max(lcsCount2, lcsCount3)); } // Method2A1()- recursive solution with memoization (Top-down approach caching on method level) public static int LCSubStrM2A1(char[] X, char[] Y, int m, int n, int lcsCount, Integer[][][] dp) { if (m <= 0 || n <= 0) return lcsCount; if (dp[m][n][lcsCount] != null) return dp[m][n][lcsCount]; int lcsCount1=lcsCount; if (X[m - 1] == Y[n - 1]) lcsCount1 = LCSubStrM2A1(X, Y, m - 1, n - 1, lcsCount + 1, dp); int lcsCount2 = LCSubStrM2A1(X, Y, m, n - 1, 0, dp); int lcsCount3 = LCSubStrM2A1(X, Y, m - 1, n, 0, dp); return dp[m][n][lcsCount] = Math.max(lcsCount1, Math.max(lcsCount2, lcsCount3)); } // Method2A2()- recursive solution with memoization (Top-down approach caching on global level) public static int LCSubStrM2A2(char[] X, char[] Y, int m, int n, int lcsCount) { if (m <= 0 || n <= 0) return lcsCount; if (dp[m][n][lcsCount] != null) return dp[m][n][lcsCount]; int lcsCount1=lcsCount; if (X[m - 1] == Y[n - 1]) lcsCount1 = LCSubStrM2A2(X, Y, m - 1, n - 1, lcsCount + 1); int lcsCount2 = LCSubStrM2A2(X, Y, m, n - 1, 0); int lcsCount3 = LCSubStrM2A2(X, Y, m - 1, n, 0); return dp[m][n][lcsCount] = Math.max(lcsCount1, Math.max(lcsCount2, lcsCount3)); } // Method3()- DP solution(Bottom up approach) // time complexity - O(m*n) // space complexity - O(m*n) public static int LCSubStrA3(char[] X, char[] Y, int m, int n) { int memo[][] = new int[m + 1][n + 1]; int result = 0; ```

``` for (int i = 0; i <= m; i++) { for (int j = 0; j <= n; j++) { if (i == 0 || j == 0) { memo[i][j] = 0; } else if (X[i - 1] == Y[j - 1]) { memo[i][j] = memo[i - 1][j - 1] + 1; result = Math.max(result, memo[i][j]); } else { memo[i][j] = 0; } } } cache = memo; return result; }```

``` public static int substrLength(String str1, String str2){ //photograph,tomography int count=0,mCount= 0; for(int i=0;i<str1.length();i++){ for(int j=0;j<str2.length();j++){ if(str1.charAt(i)== str2.charAt(j)){ count =0; for(int k=0;(k+i)<str1.length()&&(k+j)mCount) mCount =count; } } return mCount; } ```