Fixed Here
Fixed Here
I've
categorized them into core types and included common problem patterns, recurrence
relations, and state definitions. This covers every possible DP pattern you’ll
encounter.
Recurrence:
Variants:
Subset Sum
Partition Equal Subset Sum
Target Sum
Coin Change (minimum coins to reach target)
Last Stone Weight II
Like 0/1 knapsack but you can take an element infinite times.
State: dp[i][j] = maximum/minimum value using the first i elements with capacity j.
Recurrence:
Variants:
Recurrence:
Variants:
Recurrence:
Variants:
Recurrence:
Variants:
Recurrence:
Variants:
✅ 7. Partition DP Type
Pattern:
Recurrence:
Variants:
Recurrence:
dp[mask] = min(dp[mask - {i}] + cost)dp[mask] = \min_{i \in mask} (dp[mask \setminus \{i\}] +
cost)dp[mask]=i∈maskmin(dp[mask∖{i}]+cost)
Variants:
✅ 9. Two-Dimensional DP Type
Pattern:
Recurrence:
Variants:
Recurrence:
dp[i][j]=∑k∈transitionsP(k)⋅dp[k]dp[i][j] = \sum_{k \in \text{transitions}} P(k) \cdot dp[k]dp[i]
[j]=k∈transitions∑P(k)⋅dp[k]
Variants:
Recurrence:
Variants:
Decode Ways
Climbing Stairs
Counting Binary Trees
State: dp[i][j] = best score the current player can achieve in the range i, j
Recurrence:
Variants:
Recurrence:
Variants:
Recurrence:
Variants:
Recurrence:
dp[pos][tight][sum]=∑d=0limitdp[pos+1][tight′][sum+d]dp[pos][tight][sum] = \sum_{d=0}^{\
text{limit}} dp[pos + 1][tight'][sum + d]dp[pos][tight][sum]=d=0∑limitdp[pos+1][tight′][sum+d]
Variants:
4o
You said:
ChatGPT said:
Alright, here are code snippets for each of the 15 dynamic programming templates. I'll
write them in C++ for consistency and clarity.
return dp[n][W];
}
cpp
CopyEdit
int unboundedKnapsack(vector<int>& weights, vector<int>& values, int W) {
int n = weights.size();
vector<int> dp(W + 1, 0);
return dp[W];
}
cpp
CopyEdit
int LCS(string s1, string s2) {
int n = s1.size(), m = s2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
return dp[n][m];
}
cpp
CopyEdit
int LIS(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n, 1);
int ans = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
ans = max(ans, dp[i]);
}
return ans;
}
cpp
CopyEdit
int matrixChain(vector<int>& arr) {
int n = arr.size() - 1;
vector<vector<int>> dp(n, vector<int>(n, INT_MAX));
cpp
CopyEdit
int longestPalindromeSubseq(string s) {
int n = s.size();
vector<vector<int>> dp(n, vector<int>(n, 0));
✅ 7. Partition DP Type
Problem: Minimum cuts to make substrings palindrome.
cpp
CopyEdit
int minCut(string s) {
int n = s.size();
vector<int> dp(n, INT_MAX);
vector<vector<bool>> isPalin(n, vector<bool>(n, false));
cpp
CopyEdit
const int INF = 1e9;
int tsp(vector<vector<int>>& dist) {
int n = dist.size();
vector<vector<int>> dp(1 << n, vector<int>(n, INF));
dp[1][0] = 0;
for (int mask = 1; mask < (1 << n); mask++) {
for (int u = 0; u < n; u++) {
if (mask & (1 << u)) {
for (int v = 0; v < n; v++) {
if (!(mask & (1 << v))) {
int newMask = mask | (1 << v);
dp[newMask][v] = min(dp[newMask][v],
dp[mask][u] + dist[u][v]);
}
}
}
}
}
return ans;
}
YESSSS
ChatGPT said:
Alright, let’s keep the momentum going! Here's the next set of Dynamic
Programming templates with C++ code snippets:
return dp[n][target];
}
return dp[k][n];
}
return dp[n];
}
✅ 14. Bitmask DP Type
Problem: Assign tasks to people with minimum cost using a bitmask.
Recurrence:
return prev[m];
}
👉 What’s next? Want to practice some DP problems now or go deeper into any
template? 😏
You said:
ChatGPT said:
Graph problems revolve around key patterns like traversal, shortest paths, MST,
topological sorting, and flow algorithms. Let’s lock them down one by one with clean
C++ code snippets:
✅ 1. BFS/DFS Traversal
Problem: Traverse a graph using BFS or DFS.
Technique: Use a queue for BFS and stack/recursion for DFS.
🚀 BFS
cpp
CopyEdit
void bfs(vector<vector<int>>& graph, int start) {
int n = graph.size();
vector<bool> visited(n, false);
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int node = q.front();
q.pop();
cout << node << " ";
🚀 DFS
cpp
CopyEdit
void dfs(int node, vector<vector<int>>& graph, vector<bool>& visited) {
visited[node] = true;
cout << node << " ";
✅ 2. Connected Components
Problem: Count the number of connected components.
Technique: Use DFS/BFS and count the number of times you start a new traversal.
cpp
CopyEdit
int countComponents(int n, vector<vector<int>>& edges) {
vector<vector<int>> graph(n);
for (auto& edge : edges) {
graph[edge[0]].push_back(edge[1]);
graph[edge[1]].push_back(edge[0]);
}
return count;
}
✅ 3. Bipartite Check
Problem: Check if a graph is bipartite.
Technique: Use BFS and alternate colors.
cpp
CopyEdit
bool isBipartite(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> color(n, -1);
while (!q.empty()) {
int node = q.front(); q.pop();
cpp
CopyEdit
bool dfs(int node, int parent, vector<vector<int>>& graph, vector<bool>& visited) {
visited[node] = true;
return false;
}
bool hasCycle(vector<vector<int>>& graph) {
int n = graph.size();
vector<bool> visited(n, false);
return false;
}
cpp
CopyEdit
bool dfs(int node, vector<vector<int>>& graph, vector<int>& state) {
state[node] = 1; // visiting
return false;
}
✅ 6. Topological Sorting
Problem: Find a valid topological order in a DAG.
Technique: Use Kahn’s Algorithm (BFS).
cpp
CopyEdit
vector<int> topologicalSort(vector<vector<int>>& graph) {
int n = graph.size();
vector<int> indegree(n, 0);
queue<int> q;
for (int i = 0; i < n; i++) {
if (indegree[i] == 0) q.push(i);
}
vector<int> order;
while (!q.empty()) {
int node = q.front(); q.pop();
order.push_back(node);
return order;
}
✅ 7. Dijkstra's Algorithm (Single Source
Shortest Path)
Problem: Find shortest path in a weighted graph (no negative edges).
Technique: Use a priority_queue.
cpp
CopyEdit
vector<int> dijkstra(int n, vector<vector<pair<int, int>>>& graph, int src) {
vector<int> dist(n, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
dist[src] = 0;
pq.push({0, src});
while (!pq.empty()) {
auto [d, node] = pq.top(); pq.pop();
if (d > dist[node]) continue;
return dist;
}
cpp
CopyEdit
vector<int> bellmanFord(int n, vector<vector<int>>& edges, int src) {
vector<int> dist(n, INT_MAX);
dist[src] = 0;
return dist;
}
cpp
CopyEdit
void floydWarshall(vector<vector<int>>& dist) {
int n = dist.size();
You said:
NOW TREES
ChatGPT said:
Tree problems revolve around traversal, lowest common ancestor (LCA), diameter,
subtree sums, and dynamic programming on trees. Let’s rip through them one by one
with clean C++ code snippets:
🚀 Iterative Inorder
cpp
CopyEdit
void inorder(TreeNode* root) {
stack<TreeNode*> st;
TreeNode* curr = root;
cpp
CopyEdit
void levelOrder(TreeNode* root) {
if (!root) return;
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode* node = q.front(); q.pop();
cout << node->val << " ";
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
}
}
✅ 3. Height of a Tree
Problem: Find the height (or depth) of a tree.
Technique: Use DFS.
cpp
CopyEdit
int height(TreeNode* root) {
if (!root) return 0;
return 1 + max(height(root->left), height(root->right));
}
cpp
CopyEdit
TreeNode* LCA(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root || root == p || root == q) return root;
TreeNode* left = LCA(root->left, p, q);
TreeNode* right = LCA(root->right, p, q);
if (left && right) return root;
return left ? left : right;
}
✅ 5. Diameter of a Tree
Problem: Find the length of the longest path between two nodes.
Technique: Use DFS and maintain max height + subtree height.
cpp
CopyEdit
int diameter(TreeNode* root, int& maxDiameter) {
if (!root) return 0;
int left = diameter(root->left, maxDiameter);
int right = diameter(root->right, maxDiameter);
cpp
CopyEdit
int maxPathSum(TreeNode* root, int& maxSum) {
if (!root) return 0;
cpp
CopyEdit
int kthSmallest(TreeNode* root, int& k) {
if (!root) return -1;
k--;
if (k == 0) return root->val;
✅ 8. Subtree Sum
Problem: Find the sum of all nodes in a subtree.
Technique: Use DFS.
cpp
CopyEdit
int subtreeSum(TreeNode* root) {
if (!root) return 0;
return root->val + subtreeSum(root->left) + subtreeSum(root->right);
}
🚀 Serialize
cpp
CopyEdit
string serialize(TreeNode* root) {
if (!root) return "#";
return to_string(root->val) + "," + serialize(root->left) + "," + serialize(root->right);
}
🚀 Deserialize
cpp
CopyEdit
TreeNode* deserializeHelper(queue<string>& nodes) {
string val = nodes.front(); nodes.pop();
if (val == "#") return nullptr;
return root;
}
TreeNode* deserialize(string data) {
queue<string> nodes;
stringstream ss(data);
string item;
while (getline(ss, item, ',')) nodes.push(item);
return deserializeHelper(nodes);
}
✅ 10. Construct a Tree from
Preorder/Inorder/Postorder
Problem: Rebuild a tree from traversal order.
Technique: Use recursion and array partitioning.
cpp
CopyEdit
void flatten(TreeNode* root) {
TreeNode* prev = nullptr;
function<void(TreeNode*)> dfs = [&](TreeNode* node) {
if (!node) return;
dfs(node->right);
dfs(node->left);
node->right = prev;
node->left = nullptr;
prev = node;
};
dfs(root);
}
You said:
ChatGPT said:
cpp
CopyEdit
class MyStack {public:
vector<int> st;
void push(int x) {
st.push_back(x);
}
void pop() {
st.pop_back();
}
int top() {
return st.back();
}
bool empty() {
return st.empty();
}
};
cpp
CopyEdit
class MyQueue {public:
queue<int> q;
void push(int x) {
q.push(x);
}
void pop() {
q.pop();
}
int front() {
return q.front();
}
bool empty() {
return q.empty();
}
};
cpp
CopyEdit
vector<int> nextGreaterElement(vector<int>& nums) {
vector<int> res(nums.size(), -1);
stack<int> st;
return res;
}
cpp
CopyEdit
vector<int> nextSmallerElement(vector<int>& nums) {
vector<int> res(nums.size(), -1);
stack<int> st;
return res;
}
✅ 5. Min Stack
Problem: Design a stack that supports push, pop, top, and retrieving the minimum
element in O(1).
Technique: Maintain a separate min stack.
cpp
CopyEdit
class MinStack {public:
stack<int> st, minSt;
void push(int x) {
st.push(x);
if (minSt.empty() || x <= minSt.top()) {
minSt.push(x);
}
}
void pop() {
if (st.top() == minSt.top()) minSt.pop();
st.pop();
}
int top() {
return st.top();
}
int getMin() {
return minSt.top();
}
};
return maxArea;
}
cpp
CopyEdit
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> res;
dq.push_back(i);
if (i >= k - 1) res.push_back(nums[dq.front()]);
}
return res;
}
✅ 8. LRU Cache
Problem: Implement an LRU (Least Recently Used) Cache.
Technique: Use unordered_map + list.
cpp
CopyEdit
class LRUCache {
int capacity;
list<int> keys;
unordered_map<int, pair<int, list<int>::iterator>> cache;
public:
LRUCache(int cap) {
capacity = cap;
}
✅ 9. Valid Parentheses
Problem: Check if a string of parentheses is valid.
Technique: Use a stack.
cpp
CopyEdit
bool isValid(string s) {
stack<char> st;
for (char c : s) {
if (c == '(' || c == '{' || c == '[') {
st.push(c);
} else {
if (st.empty()) return false;
if ((c == ')' && st.top() != '(') ||
(c == '}' && st.top() != '{') ||
(c == ']' && st.top() != '[')) {
return false;
}
st.pop();
}
}
return st.empty();
}
✅ 10. Implement Stack Using Queues
Problem: Implement a stack using two queues.
Technique: Push all elements to one queue and reverse them during pop.
cpp
CopyEdit
class MyStack {public:
queue<int> q;
void push(int x) {
q.push(x);
for (int i = 0; i < q.size() - 1; i++) {
q.push(q.front());
q.pop();
}
}
int pop() {
int top = q.front();
q.pop();
return top;
}
int top() {
return q.front();
}
bool empty() {
return q.empty();
}
};
cpp
CopyEdit
class MyQueue {public:
stack<int> in, out;
void push(int x) {
in.push(x);
}
int pop() {
if (out.empty()) {
while (!in.empty()) {
out.push(in.top());
in.pop();
}
}
int front = out.top();
out.pop();
return front;
}
int peek() {
if (out.empty()) {
while (!in.empty()) {
out.push(in.top());
in.pop();
}
}
return out.top();
}
bool empty() {
return in.empty() && out.empty();
}
};
You said:
ChatGPT said:
cpp
CopyEdit
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
✅ 2. Insert at Beginning
Problem: Insert a node at the beginning of a linked list.
Technique: Adjust the head pointer.
cpp
CopyEdit
ListNode* insertAtBeginning(ListNode* head, int val) {
ListNode* newNode = new ListNode(val);
newNode->next = head;
return newNode;
}
✅ 3. Insert at End
Problem: Insert a node at the end of a linked list.
Technique: Traverse to the last node and link the new node.
cpp
CopyEdit
ListNode* insertAtEnd(ListNode* head, int val) {
ListNode* newNode = new ListNode(val);
if (!head) return newNode;
return head;
}
cpp
CopyEdit
ListNode* deleteNode(ListNode* head, int val) {
if (!head) return head;
if (head->val == val) return head->next;
cpp
CopyEdit
ListNode* reverseList(ListNode* head) {
ListNode *prev = NULL, *curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
cpp
CopyEdit
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
cpp
CopyEdit
bool hasCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}
cpp
CopyEdit
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return NULL;
}
cpp
CopyEdit
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* tail = &dummy;
cpp
CopyEdit
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
ListNode *slow = &dummy, *fast = &dummy;
cpp
CopyEdit
ListNode* middleNode(ListNode* head) {
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
cpp
CopyEdit
ListNode* partition(ListNode* head, int x) {
ListNode before(0), after(0);
ListNode *beforeTail = &before, *afterTail = &after;
while (head) {
if (head->val < x) {
beforeTail->next = head;
beforeTail = beforeTail->next;
} else {
afterTail->next = head;
afterTail = afterTail->next;
}
head = head->next;
}
afterTail->next = NULL;
beforeTail->next = after.next;
return before.next;
}
cpp
CopyEdit
class Node {public:
int val;
Node* next;
Node* random;
Node(int x) : val(x), next(NULL), random(NULL) {}
};
Node* copyRandomList(Node* head) {
if (!head) return nullptr;
curr = head;
while (curr) {
mp[curr]->next = mp[curr->next];
mp[curr]->random = mp[curr->random];
curr = curr->next;
}
return mp[head];
}
cpp
CopyEdit
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* curr = &dummy;
int carry = 0;
You said:
NOW ARRAYS
ChatGPT said:
✅ 1. Linear Search
Problem: Search for an element in an array.
Technique: Simple linear traversal.
cpp
CopyEdit
int search(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == target) return i;
}
return -1;
}
✅ 2. Binary Search
Problem: Find element in a sorted array.
Technique: Divide and conquer.
cpp
CopyEdit
int binarySearch(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) return mid;
else if (nums[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
✅ 3. Two Pointers
Problem: Find pair with given sum.
Technique: Two-pointer approach.
cpp
CopyEdit
vector<int> twoSum(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) return {left, right};
else if (sum < target) left++;
else right--;
}
return {};
}
cpp
CopyEdit
int maxSum(vector<int>& nums, int k) {
int windowSum = 0, maxSum = 0;
for (int i = 0; i < k; i++) windowSum += nums[i];
maxSum = windowSum;
for (int i = k; i < nums.size(); i++) {
windowSum += nums[i] - nums[i - k];
maxSum = max(maxSum, windowSum);
}
return maxSum;
}
cpp
CopyEdit
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, sum = 0, minLen = INT_MAX;
for (int right = 0; right < nums.size(); right++) {
sum += nums[right];
while (sum >= target) {
minLen = min(minLen, right - left + 1);
sum -= nums[left++];
}
}
return minLen == INT_MAX ? 0 : minLen;
}
✅ 6. Prefix Sum
Problem: Find sum of elements between indices i and j.
Technique: Precompute prefix sums.
cpp
CopyEdit
vector<int> prefixSum;
void buildPrefixSum(vector<int>& nums) {
prefixSum.resize(nums.size());
prefixSum[0] = nums[0];
for (int i = 1; i < nums.size(); i++) {
prefixSum[i] = prefixSum[i - 1] + nums[i];
}
}
int rangeSum(int left, int right) {
if (left == 0) return prefixSum[right];
return prefixSum[right] - prefixSum[left - 1];
}
cpp
CopyEdit
int maxSubArray(vector<int>& nums) {
int currMax = nums[0], globalMax = nums[0];
for (int i = 1; i < nums.size(); i++) {
currMax = max(nums[i], currMax + nums[i]);
globalMax = max(globalMax, currMax);
}
return globalMax;
}
✅ 8. Find Duplicates
Problem: Find duplicate elements in an array.
Technique: Use set or negative marking.
cpp
CopyEdit
vector<int> findDuplicates(vector<int>& nums) {
vector<int> res;
for (int num : nums) {
int index = abs(num) - 1;
if (nums[index] < 0) res.push_back(abs(num));
nums[index] = -nums[index];
}
return res;
}
cpp
CopyEdit
int missingNumber(vector<int>& nums) {
int n = nums.size();
int sum = n * (n + 1) / 2;
for (int num : nums) sum -= num;
return sum;
}
cpp
CopyEdit
void nextPermutation(vector<int>& nums) {
int i = nums.size() - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) i--;
if (i >= 0) {
int j = nums.size() - 1;
while (nums[j] <= nums[i]) j--;
swap(nums[i], nums[j]);
}
reverse(nums.begin() + i + 1, nums.end());
}
cpp
CopyEdit
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
int left = 0, right = matrix[0].size() - 1;
int top = 0, bottom = matrix.size() - 1;
while (left <= right && top <= bottom) {
for (int i = left; i <= right; i++) res.push_back(matrix[top][i]);
top++;
for (int i = top; i <= bottom; i++) res.push_back(matrix[i][right]);
right--;
if (top <= bottom) for (int i = right; i >= left; i--) res.push_back(matrix[bottom][i]);
bottom--;
if (left <= right) for (int i = bottom; i >= top; i--) res.push_back(matrix[i][left]);
left++;
}
return res;
}
✅ 13. Rotate Array
Problem: Rotate an array by k steps.
Technique: Reverse in parts.
cpp
CopyEdit
void rotate(vector<int>& nums, int k) {
k %= nums.size();
reverse(nums.begin(), nums.end());
reverse(nums.begin(), nums.begin() + k);
reverse(nums.begin() + k, nums.end());
}
cpp
CopyEdit
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
mp[0] = 1;
int sum = 0, count = 0;
for (int num : nums) {
sum += num;
if (mp.count(sum - k)) count += mp[sum - k];
mp[sum]++;
}
return count;
}
You said:
MAKE ME A STRINGS GOD THE ALMIGHTY GOD OF STRINGS NOBODY IN THE UNIVERSE IS BETTER
THAN ME IN STRINGS
ChatGPT said:
Memory updated
✅ 1. Reverse a String
Problem: Reverse a given string in-place.
Technique: Two-pointer swap.
cpp
CopyEdit
void reverseString(string& s) {
int left = 0, right = s.size() - 1;
while (left < right) swap(s[left++], s[right--]);
}
✅ 2. Palindrome Check
Problem: Check if a string is a palindrome.
Technique: Two-pointer check.
cpp
CopyEdit
bool isPalindrome(string s) {
int left = 0, right = s.size() - 1;
while (left < right) {
if (s[left++] != s[right--]) return false;
}
return true;
}
cpp
CopyEdit
string longestPalindrome(string s) {
int start = 0, maxLen = 0;
for (int i = 0; i < s.size(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = max(len1, len2);
if (len > maxLen) {
start = i - (len - 1) / 2;
maxLen = len;
}
}
return s.substr(start, maxLen);
}
int expandAroundCenter(string& s, int left, int right) {
while (left >= 0 && right < s.size() && s[left] == s[right]) {
left--;
right++;
}
return right - left - 1;
}
cpp
CopyEdit
vector<int> kmp(string text, string pattern) {
int n = text.size(), m = pattern.size();
vector<int> lps(m, 0), res;
// Pattern search
for (int i = 0, j = 0; i < n; ) {
if (text[i] == pattern[j]) i++, j++;
if (j == m) res.push_back(i - j), j = lps[j - 1];
else if (i < n && text[i] != pattern[j]) j ? j = lps[j - 1] : i++;
}
return res;
}
cpp
CopyEdit
vector<int> computeLPS(string pattern) {
int n = pattern.size();
vector<int> lps(n, 0);
for (int i = 1, len = 0; i < n; ) {
if (pattern[i] == pattern[len]) lps[i++] = ++len;
else if (len) len = lps[len - 1];
else lps[i++] = 0;
}
return lps;
}
cpp
CopyEdit
vector<int> zFunction(string s) {
int n = s.size();
vector<int> z(n, 0);
for (int i = 1, l = 0, r = 0; i < n; i++) {
if (i <= r) z[i] = min(r - i + 1, z[i - l]);
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) z[i]++;
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
return z;
}
cpp
CopyEdit
const int BASE = 31;const int MOD = 1e9 + 9;
vector<int> rabinKarp(string text, string pattern) {
int n = text.size(), m = pattern.size();
long long patternHash = 0, hash = 0, power = 1;
vector<int> res;
cpp
CopyEdit
struct TrieNode {
TrieNode* children[26] = {};
bool isEnd = false;
};
class Trie {public:
TrieNode* root = new TrieNode();
cpp
CopyEdit
string minWindow(string s, string t) {
vector<int> count(128, 0);
for (char c : t) count[c]++;
int left = 0, minLen = INT_MAX, minStart = 0, total = t.size();
You said:
ChatGPT said:
Memory updated
🚀 HASHING FUNDAMENTALS
🔹 1. What is Hashing?
Hashing is a method to map data to a fixed-size value (hash).
Uses a hash function to map keys to a fixed-size table.
Efficient for insertion, deletion, and search — average time complexity is O(1).
HASHING TECHNIQUES
✅ 1. Direct Addressing
Simple array-based mapping.
Only works if keys are small and non-negative integers.
cpp
CopyEdit
int table[1000] = {0};
void insert(int key) {
table[key] = 1;
}
bool search(int key) {
return table[key] == 1;
}
void remove(int key) {
table[key] = 0;
}
cpp
CopyEdit
const int MOD = 10007;
vector<int> table[MOD];
void insert(int key) {
int h = key % MOD;
table[h].push_back(key);
}
bool search(int key) {
int h = key % MOD;
for (int x : table[h]) if (x == key) return true;
return false;
}
void remove(int key) {
int h = key % MOD;
table[h].erase(remove(table[h].begin(), table[h].end(), key), table[h].end());
}
✅ 3. Open Addressing (Linear Probing)
If a collision occurs, search for the next available slot.
Use linear probing, quadratic probing, or double hashing.
🔥 Linear Probing
cpp
CopyEdit
const int MOD = 10007;int table[MOD];
void insert(int key) {
int h = key % MOD;
while (table[h] != 0) h = (h + 1) % MOD;
table[h] = key;
}
bool search(int key) {
int h = key % MOD;
while (table[h] != 0) {
if (table[h] == key) return true;
h = (h + 1) % MOD;
}
return false;
}
void remove(int key) {
int h = key % MOD;
while (table[h] != 0) {
if (table[h] == key) {
table[h] = -1;
return;
}
h = (h + 1) % MOD;
}
}
✅ 4. Double Hashing
If collision occurs, apply a secondary hash.
✅ 5. Polynomial Hashing
Used in string matching and pattern searching.
Treat the string as a polynomial:
H(s)=s0+s1⋅p+s2⋅p2+…+sn−1⋅pn−1mod MH(s) = s_0 + s_1 \cdot p + s_2 \cdot p^2 + \ldots + s_{n-1} \
cdot p^{n-1} \mod MH(s)=s0+s1⋅p+s2⋅p2+…+sn−1⋅pn−1modM
🔥 Code:
cpp
CopyEdit
const int P = 31;const int MOD = 1e9 + 9;
long long hashString(string s) {
long long hash = 0, p_pow = 1;
for (char c : s) {
hash = (hash + (c - 'a' + 1) * p_pow) % MOD;
p_pow = (p_pow * P) % MOD;
}
return hash;
}
✅ 6. Rolling Hash
Optimize substring search by using:
🔥 Code:
cpp
CopyEdit
const int P = 31;const int MOD = 1e9 + 9;
vector<long long> precomputeHash(string s) {
int n = s.size();
vector<long long> hash(n + 1, 0), power(n + 1, 1);
💡 TIPS FROM
GRANDMASTERS
🔥 Always use a prime modulus — reduces collisions.
🔥 Use double hashing when collisions are too high.
🔥 For string matching, use rolling hash over KMP for faster implementation.
🔥 Use Z-Function + Polynomial Hash for the most efficient string matching.
🔥 To avoid overflow, use unsigned long long or __int128.
🔥 Try using hashmaps over arrays for dynamic input sizes.