diff --git a/dsa-solutions/gfg-solutions/Easy problems/square-root.md b/dsa-solutions/gfg-solutions/Easy problems/square-root.md
index c249e2811..f0c2eb177 100644
--- a/dsa-solutions/gfg-solutions/Easy problems/square-root.md
+++ b/dsa-solutions/gfg-solutions/Easy problems/square-root.md
@@ -1,193 +1,193 @@
----
-id: square-root
-title: Square Root
-sidebar_label: Square-Root
-tags:
- - Math
- - Binary Search
-description: "This document provides solutions to the problem of finding the Square Root of an integer."
----
-
-## Problem
-
-Given an integer `x`, find the square root of `x`. If `x` is not a perfect square, then return the floor value of √x.
-
-### Examples
-
-**Example 1:**
-
-```
-Input: x = 5
-Output: 2
-Explanation: Since 5 is not a perfect square, the floor of the square root of 5 is 2.
-```
-
-**Example 2:**
-
-```
-Input: x = 4
-Output: 2
-Explanation: Since 4 is a perfect square, its square root is 2.
-```
-
-### Your Task
-
-You don't need to read input or print anything. The task is to complete the function `floorSqrt()` which takes `x` as the input parameter and returns its square root. Note: Try solving the question without using the sqrt function. The value of `x` ≥ 0.
-
-**Expected Time Complexity:** $O(log N)$
-**Expected Auxiliary Space:** $O(1)$
-
-**Constraints**
-
-- `1 ≤ x ≤ 10^7`
-
-## Solution
-
-### Intuition & Approach
-
-To find the square root of a number without using the built-in `sqrt` function, we can use binary search. This approach leverages the fact that the square root of `x` must lie between `0` and `x`. By repeatedly narrowing down the range using binary search, we can efficiently find the floor value of the square root.
-
-### Implementation
-
-
-
-
-```python
-class Solution:
- def floorSqrt(self, x: int) -> int:
- if x == 0 or x == 1:
- return x
- start, end = 1, x
- ans = 0
- while start <= end:
- mid = (start + end) // 2
- if mid * mid == x:
- return mid
- if mid * mid < x:
- start = mid + 1
- ans = mid
- else:
- end = mid - 1
- return ans
-```
-
-
-
-
-```java
-class Solution {
- long floorSqrt(long x) {
- if (x == 0 || x == 1) {
- return x;
- }
- long start = 1, end = x, ans = 0;
- while (start <= end) {
- long mid = (start + end) / 2;
- if (mid * mid == x) {
- return mid;
- }
- if (mid * mid < x) {
- start = mid + 1;
- ans = mid;
- } else {
- end = mid - 1;
- }
- }
- return ans;
- }
-}
-```
-
-
-
-
-```cpp
-class Solution {
-public:
- long long int floorSqrt(long long int x) {
- if (x == 0 || x == 1)
- return x;
- long long int start = 1, end = x, ans = 0;
- while (start <= end) {
- long long int mid = (start + end) / 2;
- if (mid * mid == x)
- return mid;
- if (mid * mid < x) {
- start = mid + 1;
- ans = mid;
- } else {
- end = mid - 1;
- }
- }
- return ans;
- }
-};
-```
-
-
-
-
-```javascript
-class Solution {
- floorSqrt(x) {
- if (x === 0 || x === 1) {
- return x;
- }
- let start = 1,
- end = x,
- ans = 0;
- while (start <= end) {
- let mid = Math.floor((start + end) / 2);
- if (mid * mid === x) {
- return mid;
- }
- if (mid * mid < x) {
- start = mid + 1;
- ans = mid;
- } else {
- end = mid - 1;
- }
- }
- return ans;
- }
-}
-```
-
-
-
-
-```typescript
-class Solution {
- floorSqrt(x: number): number {
- if (x === 0 || x === 1) {
- return x;
- }
- let start = 1,
- end = x,
- ans = 0;
- while (start <= end) {
- let mid = Math.floor((start + end) / 2);
- if (mid * mid === x) {
- return mid;
- }
- if (mid * mid < x) {
- start = mid + 1;
- ans = mid;
- } else {
- end = mid - 1;
- }
- }
- return ans;
- }
-}
-```
-
-
-
-
-## Complexity Analysis
-
-The provided solutions efficiently find the floor value of the square root of a given integer `x` using binary search. This approach ensures a time complexity of $ O(log N) and an auxiliary space complexity of $O(1)$. The algorithms are designed to handle large values of `x` up to 10^7 efficiently without relying on built-in square root functions.
-
-**Time Complexity:** $O(log N)$
-**Auxiliary Space:** $O(1)$
+---
+id: square-root
+title: Square Root
+sidebar_label: Square-Root
+tags:
+ - Math
+ - Binary Search
+description: "This document provides solutions to the problem of finding the Square Root of an integer."
+---
+
+## Problem
+
+Given an integer `x`, find the square root of `x`. If `x` is not a perfect square, then return the floor value of √x.
+
+### Examples
+
+**Example 1:**
+
+```
+Input: x = 5
+Output: 2
+Explanation: Since 5 is not a perfect square, the floor of the square root of 5 is 2.
+```
+
+**Example 2:**
+
+```
+Input: x = 4
+Output: 2
+Explanation: Since 4 is a perfect square, its square root is 2.
+```
+
+### Your Task
+
+You don't need to read input or print anything. The task is to complete the function `floorSqrt()` which takes `x` as the input parameter and returns its square root. Note: Try solving the question without using the sqrt function. The value of `x` ≥ 0.
+
+**Expected Time Complexity:** $O(log N)$
+**Expected Auxiliary Space:** $O(1)$
+
+**Constraints**
+
+- `1 ≤ x ≤ 10^7`
+
+## Solution
+
+### Intuition & Approach
+
+To find the square root of a number without using the built-in `sqrt` function, we can use binary search. This approach leverages the fact that the square root of `x` must lie between `0` and `x`. By repeatedly narrowing down the range using binary search, we can efficiently find the floor value of the square root.
+
+### Implementation
+
+
+
+
+```python
+class Solution:
+ def floorSqrt(self, x: int) -> int:
+ if x == 0 or x == 1:
+ return x
+ start, end = 1, x
+ ans = 0
+ while start <= end:
+ mid = (start + end) // 2
+ if mid * mid == x:
+ return mid
+ if mid * mid < x:
+ start = mid + 1
+ ans = mid
+ else:
+ end = mid - 1
+ return ans
+```
+
+
+
+
+```java
+class Solution {
+ long floorSqrt(long x) {
+ if (x == 0 || x == 1) {
+ return x;
+ }
+ long start = 1, end = x, ans = 0;
+ while (start <= end) {
+ long mid = (start + end) / 2;
+ if (mid * mid == x) {
+ return mid;
+ }
+ if (mid * mid < x) {
+ start = mid + 1;
+ ans = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return ans;
+ }
+}
+```
+
+
+
+
+```cpp
+class Solution {
+public:
+ long long int floorSqrt(long long int x) {
+ if (x == 0 || x == 1)
+ return x;
+ long long int start = 1, end = x, ans = 0;
+ while (start <= end) {
+ long long int mid = (start + end) / 2;
+ if (mid * mid == x)
+ return mid;
+ if (mid * mid < x) {
+ start = mid + 1;
+ ans = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return ans;
+ }
+};
+```
+
+
+
+
+```javascript
+class Solution {
+ floorSqrt(x) {
+ if (x === 0 || x === 1) {
+ return x;
+ }
+ let start = 1,
+ end = x,
+ ans = 0;
+ while (start <= end) {
+ let mid = Math.floor((start + end) / 2);
+ if (mid * mid === x) {
+ return mid;
+ }
+ if (mid * mid < x) {
+ start = mid + 1;
+ ans = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return ans;
+ }
+}
+```
+
+
+
+
+```typescript
+class Solution {
+ floorSqrt(x: number): number {
+ if (x === 0 || x === 1) {
+ return x;
+ }
+ let start = 1,
+ end = x,
+ ans = 0;
+ while (start <= end) {
+ let mid = Math.floor((start + end) / 2);
+ if (mid * mid === x) {
+ return mid;
+ }
+ if (mid * mid < x) {
+ start = mid + 1;
+ ans = mid;
+ } else {
+ end = mid - 1;
+ }
+ }
+ return ans;
+ }
+}
+```
+
+
+
+
+## Complexity Analysis
+
+The provided solutions efficiently find the floor value of the square root of a given integer `x` using binary search. This approach ensures a time complexity of $ O(log N) and an auxiliary space complexity of $O(1)$. The algorithms are designed to handle large values of `x` up to 10^7 efficiently without relying on built-in square root functions.
+
+**Time Complexity:** $O(log N)$
+**Auxiliary Space:** $O(1)$
diff --git a/dsa/Algorithms/Dynamic Programming/15-Z-Algorithm.md b/dsa/Algorithms/Dynamic Programming/15-Z-Algorithm.md
new file mode 100644
index 000000000..7fcf60467
--- /dev/null
+++ b/dsa/Algorithms/Dynamic Programming/15-Z-Algorithm.md
@@ -0,0 +1,172 @@
+---
+id: z-algorithm
+title: Z-Algorithm
+sidebar_label: Z-Algorithm
+tags: [python, java, c++, programming, algorithms, dynamic programming, tutorial, in-depth]
+description: In this tutorial, we will learn about the Z-Algorithm and its implementation in Python, Java, and C++ with detailed explanations and examples.
+---
+
+# Z-Algorithm
+
+The Z-Algorithm is a linear time algorithm used for pattern matching within a string. It is commonly used to compute the Z-array, which provides information about the occurrences of a substring within a string. The Z-array for a string `S` is an array where the `i-th` position represents the length of the longest substring starting from `S[i]` that matches a prefix of `S`.
+
+## Problem Statement
+
+Given a string `S` of length `n`, the Z-array of `S` is an array `Z` of length `n` where `Z[i]` is the length of the longest substring starting from `S[i]` which is also a prefix of `S`.
+
+## Example
+
+For the string `S = "aabcaabxaaaz"`, the Z-array would be `[0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0]`.
+
+## Algorithm
+
+1. Initialize `L` and `R` to 0. These will define the interval `[L, R]` which is the rightmost segment of `S` that matches the prefix of `S`.
+2. Iterate over each character in the string and compute the Z-values based on the interval `[L, R]`.
+3. If the current index `i` is outside of `[L, R]`, calculate the Z-value directly.
+4. If `i` is within `[L, R]`, use previously computed Z-values to determine the Z-value at `i`.
+
+## Code for Z-Algorithm
+
+## Z-Algorithm
+
+The Z-Algorithm is used for string pattern matching and finding the Z-array, which represents the lengths of the longest substrings starting from each position in a string that match the prefix of the string.
+
+### Python Implementation
+
+```python
+def compute_z(s):
+ n = len(s)
+ z = [0] * n
+ l, r, k = 0, 0, 0
+ for i in range(1, n):
+ if i > r:
+ l, r = i, i
+ while r < n and s[r] == s[r - l]:
+ r += 1
+ z[i] = r - l
+ r -= 1
+ else:
+ k = i - l
+ if z[k] < r - i + 1:
+ z[i] = z[k]
+ else:
+ l = i
+ while r < n and s[r] == s[r - l]:
+ r += 1
+ z[i] = r - l
+ r -= 1
+ return z
+s = "aabcaabxaaaz"
+print("Z-array:", compute_z(s))
+```
+
+### Java Implementation
+
+```java
+public class ZAlgorithm {
+ public static int[] computeZ(String s) {
+ int n = s.length();
+ int[] z = new int[n];
+ int l = 0, r = 0, k;
+ for (int i = 1; i < n; i++) {
+ if (i > r) {
+ l = r = i;
+ while (r < n && s.charAt(r) == s.charAt(r - l)) {
+ r++;
+ }
+ z[i] = r - l;
+ r--;
+ } else {
+ k = i - l;
+ if (z[k] < r - i + 1) {
+ z[i] = z[k];
+ } else {
+ l = i;
+ while (r < n && s.charAt(r) == s.charAt(r - l)) {
+ r++;
+ }
+ z[i] = r - l;
+ r--;
+ }
+ }
+ }
+ return z;
+ }
+
+ public static void main(String[] args) {
+ String s = "aabcaabxaaaz";
+ int[] z = computeZ(s);
+ System.out.print("Z-array: ");
+ for (int value : z) {
+ System.out.print(value + " ");
+ }
+ }
+}
+```
+
+### Cpp Implementation
+
+```cpp
+#include
+#include
+#include
+
+using namespace std;
+
+vector computeZ(const string& s) {
+ int n = s.length();
+ vector z(n, 0);
+ int l = 0, r = 0, k;
+ for (int i = 1; i < n; i++) {
+ if (i > r) {
+ l = r = i;
+ while (r < n && s[r] == s[r - l]) {
+ r++;
+ }
+ z[i] = r - l;
+ r--;
+ } else {
+ k = i - l;
+ if (z[k] < r - i + 1) {
+ z[i] = z[k];
+ } else {
+ l = i;
+ while (r < n && s[r] == s[r - l]) {
+ r++;
+ }
+ z[i] = r - l;
+ r--;
+ }
+ }
+ }
+ return z;
+}
+
+int main() {
+ string s = "aabcaabxaaaz";
+ vector z = computeZ(s);
+ cout << "Z-array: ";
+ for (int value : z) {
+ cout << value << " ";
+ }
+ cout << endl;
+ return 0;
+}
+```
+
+## Output
+
+`Z-array: 0 1 0 3 0 1 0 2 0 1 0 0`
+
+
+## Time Complexity
+
+The Z-Algorithm runs in $O(n)$ time complexity where `n` is the length of the string. This is due to the linear scan of the string and the efficient handling of previously computed Z-values.
+
+## Space Complexity
+
+The space complexity is $O(n)$ for storing the Z-array.
+
+## Conclusion
+
+The Z-Algorithm is an efficient method for pattern matching and string analysis, providing the Z-array in linear time. This algorithm is widely used in various applications such as substring search and pattern matching.