using System; using System.Collections.Generic; class ComputeHash { private List<long> hash; private List<long> invMod; private long mod; private long p; // Constructor to initialize hash values for the given string public ComputeHash(string s, long p, long mod) { int n = s.Length; this.hash = new List<long>(n); this.invMod = new List<long>(n); this.mod = mod; this.p = p; long pPow = 1; long hashValue = 0; for (int i = 0; i < n; i++) { char c = s[i]; // Convert character to numeric value c = (char)(c - 'A' + 1); hashValue = (hashValue + c * pPow) % this.mod; this.hash.Add(hashValue); // Compute modular inverse this.invMod.Add(ModularInverse(pPow, this.mod)); pPow = (pPow * this.p) % this.mod; } } // Helper function to compute modular inverse using extended Euclidean algorithm private long ModularInverse(long a, long m) { long m0 = m, t, q; long x0 = 0, x1 = 1; if (m == 1) return 0; while (a > 1) { q = a / m; t = m; m = a % m; a = t; t = x0; x0 = x1 - q * x0; x1 = t; } if (x1 < 0) x1 += m0; return x1; } // Function to get hash value for a substring [l, r] public long GetHash(int l, int r) { if (l == 0) { return this.hash[r]; } long window = (this.hash[r] - this.hash[l - 1] + this.mod) % this.mod; return (window * this.invMod[l]) % this.mod; } } class LongestCommonSubstring { // Function to check if a common substring of length k exists private static bool Exists(int k, string X, string Y, ComputeHash hashX1, ComputeHash hashX2, ComputeHash hashY1, ComputeHash hashY2) { for (int i = 0; i <= X.Length - k; i++) { for (int j = 0; j <= Y.Length - k; j++) { if (X.Substring(i, k) == Y.Substring(j, k)) { return true; } } } return false; } // Function to find the length of the longest common substring of X and Y private static int LongestCommonSubstr(string X, string Y) { int n = X.Length; int m = Y.Length; long p1 = 31; long p2 = 37; long m1 = (long)Math.Pow(10, 9) + 9; long m2 = (long)Math.Pow(10, 9) + 7; // Initialize two hash objects with different p1, p2, m1, m2 to reduce collision ComputeHash hashX1 = new ComputeHash(X, p1, m1); ComputeHash hashX2 = new ComputeHash(X, p2, m2); ComputeHash hashY1 = new ComputeHash(Y, p1, m1); ComputeHash hashY2 = new ComputeHash(Y, p2, m2); // Binary search to find the length of the longest common substring int low = 0, high = Math.Min(n, m); int answer = 0; while (low <= high) { int mid = (low + high) / 2; if (Exists(mid, X, Y, hashX1, hashX2, hashY1, hashY2)) { answer = mid; low = mid + 1; } else { high = mid - 1; } } return answer; } static void Main() { string X = "GeeksforGeeks"; string Y = "GeeksQuiz"; Console.WriteLine(LongestCommonSubstr(X, Y)); // Output: 5 } }