0% found this document useful (0 votes)
17 views16 pages

Advanced Algorithms Lab Manual

The document is a student lab manual for Advanced Algorithms at BVRITHYDERABAD College of Engineering for Women, detailing various algorithms including Warshall, Rabin-Karp, KMP, Horspool, Ford-Fulkerson, Dijkstra, Boyer-Moore, and the 0/1 Knapsack problem. Each algorithm is accompanied by Python implementations and example outputs. The manual serves as a practical guide for M.Tech students in their second semester.

Uploaded by

24wh1d5807
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views16 pages

Advanced Algorithms Lab Manual

The document is a student lab manual for Advanced Algorithms at BVRITHYDERABAD College of Engineering for Women, detailing various algorithms including Warshall, Rabin-Karp, KMP, Horspool, Ford-Fulkerson, Dijkstra, Boyer-Moore, and the 0/1 Knapsack problem. Each algorithm is accompanied by Python implementations and example outputs. The manual serves as a practical guide for M.Tech students in their second semester.

Uploaded by

24wh1d5807
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

BVRITHYDERABAD COLLEGE OF ENGINEERING

FOR WOMEN
ADVANCED ALGORITHMS
[Link] (1ST YEAR 2ND SEM)
STUDENT LAB MANUAL
CYCLE-2

-JHANSI RENUKA.T
ASSISTANT PROFESSOR
DEPARTMENT OF CSE

1|Page
6. Implement Warshall algorithm

def warshall(graph):
V = len(graph)
closure = [row[:] for row in graph] # Create a copy of the graph

for k in range(V):
for i in range(V):
for j in range(V):
closure[i][j] = closure[i][j] or (closure[i][k] and closure[k][j])

return closure

# Example usage:
graph = [
[1, 1, 0, 1],
[0, 1, 1, 0],
[0, 0, 1, 1],
[0, 0, 0, 1]
]

closure = warshall(graph)
for row in closure:
print(row)

OUTPUT:

[1, 1, 1, 1]
[0, 1, 1, 1]
[0, 0, 1, 1]
[0, 0, 0, 1]

2|Page
7. Implement the Rabin Karp algorithm.

def rabin_karp_search(text: str, pattern: str, d: int = 256, q: int = 101):


"""Find and print all starting indices of pattern in text."""
n, m = len(text), len(pattern)
if m > n:
return

h = pow(d, m - 1, q) # Value for highest-order digit


p_hash = 0 # Hash value for pattern
t_hash = 0 # Hash value for text window

# Initial hash computation


for i in range(m):
p_hash = (d * p_hash + ord(pattern[i])) % q
t_hash = (d * t_hash + ord(text[i])) % q

for i in range(n - m + 1):


# If hashes match, verify substring
if p_hash == t_hash:
if text[i:i + m] == pattern:
print(f"Pattern found at index {i}")

# Compute next window hash


if i < n - m:
t_hash = (d * (t_hash - ord(text[i]) * h) + ord(text[i + m])) % q
if t_hash < 0:
t_hash += q

if __name__ == "__main__":
txt = "THIS IS A TEST TEXT"
pat = "TEST"
rabin_karp_search(txt, pat)
print("---")
txt2 = "AABAACAADAABAABA"
pat2 = "AABA"
rabin_karp_search(txt2, pat2)

OUTPUT:

Pattern found at index 10


---
Pattern found at index 0
Pattern found at index 9
Pattern found at index 12

3|Page
8. Implement the KMP algorithm.

def compute_lps(pat: str) -> list[int]:


"""Compute the LPS (Longest Proper Prefix which is also Suffix) array."""
m = len(pat)
lps = [0] * m
length = 0 # length of the previous longest prefix suffix
i=1

while i < m:
if pat[i] == pat[length]:
length += 1
lps[i] = length
i += 1
else:
if length != 0:
length = lps[length - 1]
# don't increment i here
else:
lps[i] = 0
i += 1
return lps

def kmp_search(txt: str, pat: str) -> list[int]:


"""Return list of start indices where pat is found in txt."""
n, m = len(txt), len(pat)
if m == 0:
return list(range(n + 1))
if m > n:
return []

lps = compute_lps(pat)
matches = []

i = j = 0 # pointers for txt and pat


while i < n:
if txt[i] == pat[j]:
i += 1
j += 1

if j == m:
[Link](i - j)
j = lps[j - 1]
else:
if j != 0:
j = lps[j - 1]
else:
i += 1

return matches

4|Page
if __name__ == "__main__":
text1 = "THIS IS A TEST TEXT"
pattern1 = "TEST"
print("Matches in text1:", kmp_search(text1, pattern1))

text2 = "AABAACAADAABAABA"
pattern2 = "AABA"
print("Matches in text2:", kmp_search(text2, pattern2))

OUTPUT:

Matches in text1: [10]


Matches in text2: [0, 9, 12]

5|Page
9. Implement Harspool algorithm

def preprocess_shift(pat: str, sigma: int = 256) -> list[int]:


"""Build shift table for Horspool algorithm."""
m = len(pat)
table = [m] * sigma
for i in range(m - 1):
table[ord(pat[i])] = m - 1 - i
return table

def horspool_search(text: str, pat: str) -> list[int]:


"""
Return list of starting indices where `pat` occurs in `text`
using Horspool's algorithm.
"""
n, m = len(text), len(pat)
if m == 0:
return list(range(n + 1))
if m > n:
return []

shift = preprocess_shift(pat)
matches = []
i=0
while i <= n - m:
# Compare from end of pattern backwards
k=m-1
while k >= 0 and pat[k] == text[i + k]:
k -= 1
if k < 0:
[Link](i)
# Determine shift amount: use char following the window
next_char = text[i + m - 1]
i += shift[ord(next_char)]
return matches

if __name__ == "__main__":
t1 = "THIS IS A TEST TEXT"
p1 = "TEST"
print("Matches in t1:", horspool_search(t1, p1))

t2 = "AABAACAADAABAABA"
p2 = "AABA"
print("Matches in t2:", horspool_search(t2, p2))

OUTPUT:

Matches in t1: [10]


Matches in t2: [0, 9, 12]

6|Page
10. Implement max-flow problem.

from collections import deque

def bfs(rgraph, s, t, parent):


visited = [False] * len(rgraph)
queue = deque([s])
visited[s] = True

while queue:
u = [Link]()
for v, cap in enumerate(rgraph[u]):
if not visited[v] and cap > 0:
[Link](v)
visited[v] = True
parent[v] = u
if v == t:
return True
return False

def ford_fulkerson(graph, source, sink):


# Initialize residual graph
rgraph = [row[:] for row in graph]
parent = [-1] * len(graph)
max_flow = 0

# Augment while a path exists


while bfs(rgraph, source, sink, parent):
path_flow = float('inf')
v = sink
while v != source:
u = parent[v]
path_flow = min(path_flow, rgraph[u][v])
v=u

# Add path flow to total flow


max_flow += path_flow

# Update residual capacities


v = sink
while v != source:
u = parent[v]
rgraph[u][v] -= path_flow
rgraph[v][u] += path_flow
v=u

return max_flow

if __name__ == "__main__":
graph = [

7|Page
[0, 16, 13, 0, 0, 0],
[0, 0, 10, 12, 0, 0],
[0, 4, 0, 0, 14, 0],
[0, 0, 9, 0, 0, 20],
[0, 0, 0, 7, 0, 4],
[0, 0, 0, 0, 0, 0]
]
source, sink = 0, 5
result = ford_fulkerson(graph, source, sink)
print("The maximum possible flow is:", result)

OUTPUT:

The maximum possible flow is: 23

8|Page
Additional Programs
11. Develop a program to find the shortest path from a single source to all other nodes
in a weighted graph using Dijkstra’s algorithm.

import heapq

def dijkstra(graph: dict, start: str):


"""
Returns two dicts:
- distances[v]: shortest distance from start to v
- parents[v]: immediate predecessor of v along the shortest path
"""
distances = {node: float('inf') for node in graph}
distances[start] = 0
parents = {node: None for node in graph}
pq = [(0, start)]

while pq:
current_dist, u = [Link](pq)
if current_dist > distances[u]:
continue

for v, weight in graph[u]:


distance_through_u = current_dist + weight
if distance_through_u < distances[v]:
distances[v] = distance_through_u
parents[v] = u
[Link](pq, (distance_through_u, v))

return distances, parents

def reconstruct_path(parents: dict, target: str) -> list[str]:


"""Rebuilds path from start to target using the parents dict."""
path = []
while target is not None:
[Link](target)
target = parents[target]
return path[::-1]

if __name__ == "__main__":
# Example graph as adjacency list: node -> list of (neighbor, weight)
graph = {
'A': [('B', 1), ('C', 4)],
'B': [('C', 2), ('D', 5)],
'C': [('D', 1)],
'D': []
}
source = 'A'
distances, parents = dijkstra(graph, source)
9|Page
print(f"Shortest distances from {source}:")
for node, dist in [Link]():
print(f" {node}: {dist}")

print("\nShortest paths from source:")


for node in graph:
path = reconstruct_path(parents, node)
print(f" {source} -> {node}: {' -> '.join(path)}")

OUTPUT:

Shortest distances from A:


A: 0
B: 1
C: 3
D: 4

Shortest paths from source:


A -> A: A
A -> B: A -> B
A -> C: A -> B -> C
A -> D: A -> B -> C -> D

10 | P a g e
12. Implement the Boyer Moore string matching algorithm.

NO_OF_CHARS = 256

def bad_character_heuristic(pat: str) -> list[int]:


"""Build the last-occurrence table for pattern."""
bad = [-1] * NO_OF_CHARS
for i, ch in enumerate(pat):
bad[ord(ch)] = i
return bad

def boyer_moore_search(txt: str, pat: str) -> list[int]:


"""Return starting indices of all occurrences of pat in txt."""
n, m = len(txt), len(pat)
if m == 0 or m > n:
return []

bad = bad_character_heuristic(pat) # Preprocessing


matches = []
s = 0 # shift

while s <= n - m:
j=m-1

# Compare from right to left


while j >= 0 and pat[j] == txt[s + j]:
j -= 1

if j < 0:
[Link](s)
# Shift by full pattern or by last occurrence
s += m - bad[ord(txt[s + m])] if s + m < n else 1
else:
# Shift based on bad character rule
shift = max(1, j - bad[ord(txt[s + j])])
s += shift

return matches

if __name__ == "__main__":
text1 = "THIS IS A TEST TEXT"
pattern1 = "TEST"
print("Matches in text1:", boyer_moore_search(text1, pattern1))

text2 = "AABAACAADAABAABA"
pattern2 = "AABA"
print("Matches in text2:", boyer_moore_search(text2, pattern2))

11 | P a g e
OUTPUT:

Matches in text1: [10]


Matches in text2: [0, 9, 12]

12 | P a g e
13. Implementation of the 0/1 Knapsack problem using dynamic programming (bottom-
up tabulation). It outputs the maximum profit and the items chosen:
def knap_sack(wt: list[int], val: list[int], W: int):
n = len(val)
# DP table: (n+1) x (W+1)
dp = [[0] * (W + 1) for _ in range(n + 1)]

# Build table
for i in range(1, n + 1):
for w in range(1, W + 1):
if wt[i - 1] <= w:
dp[i][w] = max(val[i - 1] + dp[i - 1][w - wt[i - 1]],
dp[i - 1][w])
else:
dp[i][w] = dp[i - 1][w]

# Maximum value is dp[n][W]


max_value = dp[n][W]

# Reconstruct which items were taken


taken = []
w=W
for i in range(n, 0, -1):
# if current row value differs from the one above, item is taken
if dp[i][w] != dp[i - 1][w]:
[Link](i - 1)
w -= wt[i - 1]

[Link]()
return max_value, taken

13 | P a g e
if __name__ == "__main__":
values = [60, 100, 120]
weights = [10, 20, 30]
capacity = 50

max_val, items = knap_sack(weights, values, capacity)


print(f"Maximum value in knapsack = {max_val}")
print("Items taken (0‑based indices):", items)
print(" (weight, value):",
[ (weights[i], values[i]) for i in items ])

OUTPUT:
Maximum value in knapsack = 220
Items taken (0-based indices): [1, 2]
(weight, value): [(20, 100), (30, 120)]

14 | P a g e
14. Implementation of the graph coloring problem using backtracking.
def is_safe(vertex, graph, color, c):
for i in range(len(graph)):
if graph[vertex][i] == 1 and color[i] == c:
return False
return True

def graph_coloring_util(graph, m, color, vertex):


if vertex == len(graph):
return True

for c in range(1, m + 1):


if is_safe(vertex, graph, color, c):
color[vertex] = c
if graph_coloring_util(graph, m, color, vertex + 1):
return True
color[vertex] = 0
return False

def graph_coloring(graph, m):


color = [0] * len(graph)
if not graph_coloring_util(graph, m, color, 0):
print("Solution does not exist.")
return False

print("Solution Exists: Following are the assigned colors:")


for c in color:
print(c, end=' ')
print()
return True

15 | P a g e
# Example usage:
graph = [
[0, 1, 1, 1],
[1, 0, 1, 0],
[1, 1, 0, 1],
[1, 0, 1, 0]
]
m = 3 # Number of colors
graph_coloring(graph, m)

OUTPUT:
Solution Exists: Following are the assigned colors:
1232
True

16 | P a g e

You might also like