Back end
from fastapi import FastAPI, UploadFile, File, HTTPException
from collections import defaultdict
import re
from typing import List
app = FastAPI()
# Trie Implementation
class TrieNode:
def __init__(self):
self.children = {}
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word: str):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
def search_prefix(self, prefix: str) -> List[str]:
node = self.root
for char in prefix:
if char not in node.children:
return []
node = node.children[char]
return self._collect_words(node, prefix)
def _collect_words(self, node, prefix):
words = []
if node.is_end:
words.append(prefix)
for char, child in node.children.items():
words.extend(self._collect_words(child, prefix + char))
return words
# Hash Table Implementation
class HashTableSearch:
def __init__(self):
self.index = defaultdict(list)
def add_document(self, doc_id: int, text: str):
words = re.findall(r'\b\w+\b', text.lower())
for word in words:
self.index[word].append(doc_id)
def search(self, word: str):
return self.index.get(word.lower(), [])
trie = Trie()
hash_table = HashTableSearch()
documents = {} # Store uploaded documents
def process_document(doc_id, text):
words = re.findall(r'\b\w+\b', text.lower())
for word in words:
trie.insert(word)
hash_table.add_document(doc_id, text)
@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
content = await file.read()
text = content.decode("utf-8")
doc_id = len(documents) + 1
documents[doc_id] = text
process_document(doc_id, text)
return {"message": "Document uploaded successfully", "doc_id": doc_id}
@app.get("/search/trie/{prefix}")
def search_trie(prefix: str):
results = trie.search_prefix(prefix.lower())
return {"prefix": prefix, "matches": results}
@app.get("/search/hash/{word}")
def search_hash(word: str):
doc_ids = hash_table.search(word.lower())
return {"word": word, "documents": doc_ids}
font end
import { useState } from "react";
import axios from "axios";
export default function TextSearchApp() {
const [file, setFile] = useState(null);
const [prefix, setPrefix] = useState("");
const [word, setWord] = useState("");
const [trieResults, setTrieResults] = useState([]);
const [hashResults, setHashResults] = useState([]);
const [loading, setLoading] = useState(false);
const handleFileUpload = async (e) => {
e.preventDefault();
if (!file) return;
setLoading(true);
const formData = new FormData();
formData.append("file", file);
try {
await axios.post("http://localhost:8000/upload/", formData);
alert("File uploaded successfully");
} catch (error) {
alert("File upload failed");
setLoading(false);
};
const searchTrie = async () => {
if (!prefix) return;
try {
const res = await axios.get(`http://localhost:8000/search/trie/${prefix}`);
setTrieResults(res.data.matches);
} catch (error) {
console.error("Error fetching Trie results");
};
const searchHash = async () => {
if (!word) return;
try {
const res = await axios.get(`http://localhost:8000/search/hash/$
{word}`);
setHashResults(res.data.documents);
} catch (error) {
console.error("Error fetching Hash results");
};
return (
<div className="min-h-screen flex flex-col items-center p-6 bg-gray-
100">
<h1 className="text-3xl font-bold mb-6">Text Document Search
Engine</h1>
<form onSubmit={handleFileUpload} className="mb-6">
<input type="file" onChange={(e) => setFile(e.target.files[0])}
className="p-2 border" />
<button type="submit" className="ml-2 p-2 bg-blue-500 text-white
rounded" disabled={loading}>
{loading ? "Uploading..." : "Upload"}
</button>
</form>
<div className="flex gap-4">
<div>
<input
type="text"
placeholder="Prefix Search (Trie)"
value={prefix}
onChange={(e) => setPrefix(e.target.value)}
className="p-2 border"
/>
<button onClick={searchTrie} className="ml-2 p-2 bg-green-500
text-white rounded">
Search
</button>
<ul className="mt-2">
{trieResults.map((word, index) => (
<li key={index} className="text-gray-700">{word}</li>
))}
</ul>
</div>
<div>
<input
type="text"
placeholder="Exact Search (Hash)"
value={word}
onChange={(e) => setWord(e.target.value)}
className="p-2 border"
/>
<button onClick={searchHash} className="ml-2 p-2 bg-purple-500
text-white rounded">
Search
</button>
<ul className="mt-2">
{hashResults.map((doc, index) => (
<li key={index} className="text-gray-700">Document ID:
{doc}</li>
))}
</ul>
</div>
</div>
</div>
);