String Manipulation: Techniques and Best Practices
Read at your own pace. Code execution, quizzes, progress tracking, and the AI tutor are available in the interactive view with JavaScript enabled.
Introduction
Introduction
Why String Manipulation Matters
In the ever-evolving world of software development, string manipulation stands as a fundamental and vital skill. Strings are at the heart of human-readable data. Whether it's processing user input, reading files, generating dynamic content for web pages, or simply communicating between systems, strings are omnipresent.
But why does string manipulation matter so much, especially in coding interviews? Well, it's a microcosm of many larger problems in computer science and programming. Understanding how to manipulate strings effectively showcases your ability to handle data structures, algorithms, and problem-solving techniques. It's a skill that resonates with the daily tasks of a software developer.

Overview of String Manipulation
String manipulation involves performing various operations on strings, such as creating, modifying, searching, or transforming them. It's about understanding the characters that make up a string and how to use programming techniques to handle them.
From simple tasks like concatenating two strings to more complex ones like pattern matching and search-and-replace, string manipulation covers a wide spectrum of challenges. These challenges often appear in coding interviews as they reveal your grasp of fundamental programming concepts.
In this comprehensive guide, we'll explore the techniques and best practices for string manipulation, preparing you to excel in software engineering coding interviews. Whether you're a seasoned programmer or just starting, this course offers valuable insights and hands-on examples to hone your skills.
So, fasten your seatbelt and get ready for an exciting adventure into the world of strings! The ability to master string manipulation is not just a coding interview skill; it's a stepping stone to becoming a more effective and efficient programmer in the real world.
String Basics
String Basics

What is a String?
A string is a sequence of characters. It's used to represent text and can include letters, numbers, symbols, or even whitespace. In programming, strings are a data type that allows you to manipulate textual data.
- Immutable Strings: In languages like Java and Python, strings are immutable, meaning once created, they cannot be changed.
- Mutable Strings: In other languages, like C++, you can modify strings directly.
Let's explore some basic string operations.
Declaring and Initializing Strings
let str = "Hello World!";
str = "Hello World!"
String str = "Hello World!";
str := "Hello World!"
std::string str = "Hello World!";
Length of a String
Finding the length of a string is a fundamental operation. Here's how you can find the length in different languages:
let length = str.length;
length = len(str)
int length = str.length();
length := len(str)
int length = str.length();
Concatenating Strings
Combining two or more strings is known as concatenation. Here's how you can concatenate strings:
let concatenated = str + " Concatenated!";
concatenated = str + " Concatenated!"
String concatenated = str + " Concatenated!";
concatenated := str + " Concatenated!"
std::string concatenated = str + " Concatenated!";
Substrings and Slicing
Extracting a portion of a string is known as slicing or finding a substring. This is how you can do it:
let sliced = str.slice(0, 5); // "Hello"
sliced = str[0:5] # "Hello"
String sliced = str.substring(0, 5); // "Hello"
sliced := str[0:5] // "Hello"
std::string sliced = str.substr(0, 5); // "Hello"
Understanding these basic operations lays the foundation for more complex string manipulation tasks. From here, you can move on to more advanced techniques such as pattern matching, regular expressions, and text parsing.
String manipulation is not just about the mechanics of dealing with text; it's about thinking algorithmically and applying logical thought processes. These basic operations will become the building blocks for solving more complex problems in your coding interviews.
Fundamental String Operations
In this section, we'll explore the fundamental string operations that form the core of string manipulation. These operations are widely used in programming tasks and coding interviews.

Concatenation: How to combine strings.
Concatenation refers to the operation of joining two or more strings end-to-end. It's a fundamental technique in text processing, allowing you to create new strings by combining existing ones.
// JavaScript
var str1 = "Hello, ";
var str2 = "World!";
var result = str1.concat(str2); // "Hello, World!"
# Python
str1 = "Hello, "
str2 = "World!"
result = str1 + str2 # "Hello, World!"
// Java
String str1 = "Hello, ";
String str2 = "World!";
String result = str1 + str2; // "Hello, World!"
// C++
#include <string>
std::string str1 = "Hello, ";
std::string str2 = "World!";
std::string result = str1 + str2; // "Hello, World!"
// Go
str1 := "Hello, "
str2 := "World!"
result := str1 + str2 // "Hello, World!"
Substring Extraction: How to extract parts of a string.
Extracting substrings involves taking a portion of a string, defined by a starting and ending position. This is useful when you need to isolate specific parts of a text, such as parsing user input or processing a file.
// JavaScript
var str = "Hello, World!";
var result = str.substring(7, 12); // "World"
# Python
str = "Hello, World!"
result = str[7:12] # "World"
// Java
String str = "Hello, World!";
String result = str.substring(7, 12); // "World"
// C++
#include <string>
std::string str = "Hello, World!";
std::string result = str.substr(7, 5); // "World"
// Go
str := "Hello, World!"
result := str[7:12] // "World"
String Length: Finding the length of a string.
The length of a string refers to the number of characters it contains. Understanding the length is essential for tasks like looping through characters, validating input, or allocating memory.
// JavaScript
var str = "Hello, World!";
var length = str.length; // 13
# Python
str = "Hello, World!"
length = len(str) # 13
// Java
String str = "Hello, World!";
int length = str.length(); // 13
// C++
#include <string>
std::string str = "Hello, World!";
int length = str.length(); // 13
// Go
str := "Hello, World!"
length := len(str) // 13
String Comparison: Comparing strings for equality and ordering.
Comparing strings allows you to determine if two strings are equal or if one comes before or after the other in a given order (such as alphabetical). This is vital for sorting, searching, and validating data.
// JavaScript
var str1 = "apple";
var str2 = "orange";
var isEqual = str1 === str2; // false
var isOrdered = str1 < str2; // true
# Python
str1 = "apple"
str2 = "orange"
isEqual = str1 == str2 # false
isOrdered = str1 < str2 # true
// Java
String str1 = "apple";
String str2 = "orange";
boolean isEqual = str1.equals(str2); // false
int compareResult = str1.compareTo(str2); // negative value, str1 comes before str2
// C++
#include <string>
std::string str1 = "apple";
std::string str2 = "orange";
bool isEqual = str1 == str2; // false
bool isOrdered = str1 < str2; // true
// Go
str1 := "apple"
str2 := "orange"
isEqual := str1 == str2 // false
isOrdered := str1 < str2 // true
Case Conversion: Changing the case of characters within a string.
Case conversion involves changing the case of characters within a string, either to upper or lower case. This is useful for case-insensitive comparisons, text normalization, and user-friendly display.
// JavaScript
var str = "Hello, World!";
var upper = str.toUpperCase(); // "HELLO, WORLD!"
var lower = str.toLowerCase(); // "hello, world!"
# Python
str = "Hello, World!"
upper = str.upper() # "HELLO, WORLD!"
lower = str.lower() # "hello, world!"
// Java
String str = "Hello, World!";
String upper = str.toUpperCase(); // "HELLO, WORLD!"
String lower = str.toLowerCase(); // "hello, world!"
// C++
#include <algorithm>
#include <string>
std::string str = "Hello, World!";
std::transform(str.begin(), str.end(), str.begin(), ::toupper); // "HELLO, WORLD!"
std::transform(str.begin(), str.end(), str.begin(), ::tolower); // "hello, world!"
// Go
import "strings"
str := "Hello, World!"
upper := strings.ToUpper(str) // "HELLO, WORLD!"
lower := strings.ToLower(str) // "hello, world!"
Trimming and Padding: Removing leading/trailing spaces and adding padding.
Trimming refers to the removal of leading or trailing whitespace characters from a string. Padding, on the other hand, involves adding extra characters (such as spaces or zeros) to a string to reach a specific length. These operations are helpful for aligning text, formatting output, and cleaning up user input.
// JavaScript
var str = " Hello, World! ";
var trimmed = str.trim(); // "Hello, World!"
var padded = str.padStart(20, '0'); // "0000Hello, World! "
# Python
str = " Hello, World! "
trimmed = str.strip() # "Hello, World!"
padded = str.ljust(20, '0') # " Hello, World!000"
// Java
String str = " Hello, World! ";
String trimmed = str.trim(); // "Hello, World!"
String padded = String.format("%20s", str); // " Hello, World! "
// C++
#include <algorithm>
#include <string>
std::string str = " Hello, World! ";
str.erase(0, str.find_first_not_of(' ')); // Leading whitespace removed
str.erase(str.find_last_not_of(' ') + 1); // Trailing whitespace removed
std::string padded = str;
padded.insert(0, 4, '0'); // "0000Hello, World!"
// Go
import "strings"
str := " Hello, World! "
trimmed := strings.TrimSpace(str) // "Hello, World!"
padded := fmt.Sprintf("%-20s", str) // " Hello, World! "
```javascript
// JavaScript
// Concatenation
var str1 = "Hello, ";
var str2 = "World!";
var concatResult = str1.concat(str2);
// Substring Extraction
var str = "Hello, World!";
var substrResult = str.substring(7, 12);
// String Length
var length = str.length;
// String Comparison
var compareStr1 = "apple";
var compareStr2 = "orange";
var isEqual = compareStr1 === compareStr2;
var isOrdered = compareStr1 < compareStr2;
// Case Conversion
var upper = str.toUpperCase();
var lower = str.toLowerCase();
// Trimming and Padding
var trimStr = " Hello, World! ";
var trimmed = trimStr.trim();
var padded = trimStr.padStart(20, '0');
// Results
console.log(concatResult, substrResult, length, isEqual, isOrdered, upper, lower, trimmed, padded);
```
```python
# Python
# Concatenation
str1 = "Hello, "
str2 = "World!"
concat_result = str1 + str2
# Substring Extraction
str = "Hello, World!"
substr_result = str[7:12]
# String Length
length = len(str)
# String Comparison
compare_str1 = "apple"
compare_str2 = "orange"
is_equal = compare_str1 == compare_str2
is_ordered = compare_str1 < compare_str2
# Case Conversion
upper = str.upper()
lower = str.lower()
# Trimming and Padding
trim_str = " Hello, World! "
trimmed = trim_str.strip()
padded = trim_str.ljust(20, '0')
# Results
print(concat_result, substr_result, length, is_equal, is_ordered, upper, lower, trimmed, padded)
```
```java
// Java
public class Main {
public static void main(String[] args) {
// Concatenation
String str1 = "Hello, ";
String str2 = "World!";
String concatResult = str1 + str2;
// Substring Extraction
String str = "Hello, World!";
String substrResult = str.substring(7, 12);
// String Length
int length = str.length();
// String Comparison
String compareStr1 = "apple";
String compareStr2 = "orange";
boolean isEqual = compareStr1.equals(compareStr2);
int compareResult = compareStr1.compareTo(compareStr2);
// Case Conversion
String upper = str.toUpperCase();
String lower = str.toLowerCase();
// Trimming and Padding
String trimStr = " Hello, World! ";
String trimmed = trimStr.trim();
String padded = String.format("%20s", trimStr);
// Results
System.out.println(concatResult + " " + substrResult + " " + length + " " + isEqual + " " + (compareResult < 0) + " " + upper + " " + lower + " " + trimmed + " " + padded);
}
}
```
```cpp
// C++
#include <iostream>
#include <algorithm>
#include <string>
int main() {
// Concatenation
std::string str1 = "Hello, ";
std::string str2 = "World!";
std::string concatResult = str1 + str2;
// Substring Extraction
std::string str = "Hello, World!";
std::string substrResult = str.substr(7, 5);
// String Length
int length = str.length();
// String Comparison
std::string compareStr1 = "apple";
std::string compareStr2 = "orange";
bool isEqual = compareStr1 == compareStr2;
bool isOrdered = compareStr1 < compareStr2;
// Case Conversion
std::string upper = str;
std::transform(str.begin(), str.end(), upper.begin(), ::toupper);
std::string lower = str;
std::transform(str.begin(), str.end(), lower.begin(), ::tolower);
// Trimming and Padding
std::string trimStr = " Hello, World! ";
trimStr.erase(0, trimStr.find_first_not_of(' ')); // Leading whitespace removed
trimStr.erase(trimStr.find_last_not_of(' ') + 1); // Trailing whitespace removed
std::string padded = trimStr;
padded.insert(0, 4, '0'); // Padding
// Results
std::cout << concatResult << " " << substrResult << " " << length << " " << std::boolalpha << isEqual << " " << isOrdered << " " << upper << " " << lower << " " << trimStr << " " << padded << std::endl;
return 0;
}
```
```go
// Go
package main
import (
"fmt"
"strings"
)
func main() {
// Concatenation
str1 := "Hello, "
str2 := "World!"
concatResult := str1 + str2
// Substring Extraction
str := "Hello, World!"
substrResult := str[7:12]
// String Length
length := len(str)
// String Comparison
compareStr1 := "apple"
compareStr2 := "orange"
isEqual := compareStr1 == compareStr2
isOrdered := compareStr1 < compareStr2
// Case Conversion
upper := strings.ToUpper(str)
lower := strings.ToLower(str)
// Trimming and Padding
trimStr := " Hello, World! "
trimmed := strings.TrimSpace(trimStr)
padded := fmt.Sprintf("%-20s", trimStr)
// Results
fmt.Println(concatResult, substrResult, length, isEqual, isOrdered, upper, lower, trimmed, padded)
}
```
Searching and Pattern Matching

Searching for substrings and characters within strings is a common task in programming. Here are some techniques in different languages:
let str = "Hello World";
// indexOf to find substring
let index = str.indexOf("World");
// includes to check if substring exists
let hasHello = str.includes("Hello");
String str = "Hello World";
// indexOf to find substring
int index = str.indexOf("World");
// contains to check if substring exists
boolean hasHello = str.contains("Hello");
str = "Hello World"
# find to get index of substring
index = str.find("World")
# in operator to check if substring exists
hasHello = "Hello" in str
str := "Hello World"
// Index to find index of substring
index := strings.Index(str, "World")
// Contains to check if substring exists
hasHello := strings.Contains(str, "Hello")
string str = "Hello World";
// find to get index of substring
size_t index = str.find("World");
// check if substring exists
bool hasHello = str.find("Hello") != string::npos;
Regular expressions provide powerful pattern matching capabilities. Here is a regex example to match email addresses:
import re
pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
match = re.match(pattern, "john@email.com")
const pattern = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
const match = pattern.test("john@email.com");
Pattern pattern = Pattern.compile("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$");
Matcher match = pattern.matcher("john@email.com");
#include <regex>
std::regex pattern("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$");
bool match = std::regex_match("john@email.com", pattern);
Regex pattern = new Regex("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$");
bool match = pattern.IsMatch("john@email.com");
package main
import "regexp"
func main() {
pattern := "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$"
match, _ := regexp.MatchString(pattern, "john@email.com")
}
Wildcards like * and ? can be used for glob style pattern matching:
import glob
files = glob.glob("*.py") # matches all .py files
const files = fs.readdirSync('./*.js'); // matches all .js files
import java.io.File;
import java.io.FilenameFilter;
File dir = new File(".");
String[] files = dir.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".java");
}
});
#include <filesystem>
#include <vector>
#include <string>
std::vector<std::string> files;
for (const auto& entry : std::filesystem::directory_iterator(".")) {
if (entry.path().extension() == ".cpp") {
files.push_back(entry.path().string());
}
}
using System.IO;
string[] files = Directory.GetFiles(".", "*.cs");
package main
import (
"io/ioutil"
"strings"
)
func main() {
files, _ := ioutil.ReadDir(".")
for _, f := range files {
if strings.HasSuffix(f.Name(), ".go") {
// Do something with the file
}
}
}
This covers some basic techniques for searching, pattern matching and globbing in different languages. Regular expressions are a powerful tool for advanced string operations.
```javascript
let str = "Hello World";
let index = str.indexOf("World"); // indexOf to find substring
let hasHello = str.includes("Hello"); // includes to check if substring exists
const pattern = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
const match = pattern.test("john@email.com"); // regex example to match email addresses
```
```java
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Main {
public static void main(String[] args) {
String str = "Hello World";
int index = str.indexOf("World"); // indexOf to find substring
boolean hasHello = str.contains("Hello"); // contains to check if substring exists
Pattern pattern = Pattern.compile("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$");
Matcher match = pattern.matcher("john@email.com"); // regex example to match email addresses
}
}
```
```python
str = "Hello World"
index = str.find("World") # find to get index of substring
hasHello = "Hello" in str # in operator to check if substring exists
import re
pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
match = re.match(pattern, "john@email.com") # regex example to match email addresses
import glob
files = glob.glob("*.py") # matches all .py files using glob
```
```go
package main
import (
"strings"
)
func main() {
str := "Hello World"
index := strings.Index(str, "World") // Index to find index of substring
hasHello := strings.Contains(str, "Hello") // Contains to check if substring exists
}
```
```cpp
#include <string>
int main() {
std::string str = "Hello World";
size_t index = str.find("World"); // find to get index of substring
bool hasHello = str.find("Hello") != std::string::npos; // check if substring exists
return 0;
}
```
String Algorithms
Strings are fundamental data structures in programming, and many algorithms exist for manipulating and analyzing strings.

A palindrome is a string that reads the same backwards and forwards. Here is how to check for palindromes:
function isPalindrome(str) {
const reversed = str.split('').reverse().join('');
return str === reversed;
}
def is_palindrome(str):
return str == str[::-1]
public boolean isPalindrome(String str) {
String reversed = new StringBuilder(str).reverse().toString();
return str.equals(reversed);
}
bool isPalindrome(std::string str) {
std::string reversed = std::string(str.rbegin(), str.rend());
return str == reversed;
}
public bool IsPalindrome(string str) {
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
string reversed = new string(charArray);
return str == reversed;
}
func isPalindrome(str string) bool {
runes := []rune(str)
length := len(runes)
for i := 0; i < length/2; i++ {
runes[i], runes[length-1-i] = runes[length-1-i], runes[i]
}
reversed := string(runes)
return str == reversed
}
Two strings are anagrams if they contain the same characters in different orders. To check:
from collections import Counter
def is_anagram(str1, str2):
return Counter(str1) == Counter(str2)
function isAnagram(str1, str2) {
return str1.split('').sort().join('') ===
str2.split('').sort().join('');
}
import java.util.Arrays;
public boolean isAnagram(String str1, String str2) {
char[] charArray1 = str1.toCharArray();
char[] charArray2 = str2.toCharArray();
Arrays.sort(charArray1);
Arrays.sort(charArray2);
return Arrays.equals(charArray1, charArray2);
}
#include <algorithm>
#include <string>
bool isAnagram(std::string str1, std::string str2) {
std::sort(str1.begin(), str1.end());
std::sort(str2.begin(), str2.end());
return str1 == str2;
}
using System;
using System.Linq;
public bool IsAnagram(string str1, string str2) {
return new string(str1.OrderBy(c => c).ToArray()) ==
new string(str2.OrderBy(c => c).ToArray());
}
import "sort"
import "strings"
func isAnagram(str1, str2 string) bool {
s1 := strings.Split(str1, "")
s2 := strings.Split(str2, "")
sort.Strings(s1)
sort.Strings(s2)
return strings.Join(s1, "") == strings.Join(s2, "")
}
To find the longest common substring between two strings:
def longest_common_substring(str1, str2):
subsequences = [[0] * (len(str2) + 1) for _ in range(len(str1) + 1)]
longest = 0
lcs_idx = (0, 0)
for i in range(1, len(str1) + 1):
for j in range(1, len(str2) + 1):
if str1[i-1] == str2[j-1]:
subsequences[i][j] = 1 + subsequences[i-1][j-1]
if subsequences[i][j] > longest:
longest = subsequences[i][j]
lcs_idx = (i-1, j-1)
return str1[lcs_idx[0]-longest+1:lcs_idx[0]+1]
public String longestCommonSubstring(String str1, String str2) {
int[][] lengths = new int[str1.length() + 1][str2.length() + 1];
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.length(); i++) {
for (int j = 1; j <= str2.length(); j++) {
if (str1.charAt(i-1) == str2.charAt(j-1)) {
lengths[i][j] = lengths[i-1][j-1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i-1;
}
}
}
}
return str1.substring(longestIdx - longest + 1, longestIdx + 1);
}
function longestCommonSubstring(str1, str2) {
const lengths = Array.from({ length: str1.length + 1 }, () => Array(str2.length + 1).fill(0));
let longest = 0;
let longestIdx = 0;
for (let i = 1; i <= str1.length; i++) {
for (let j = 1; j <= str2.length; j++) {
if (str1.charAt(i - 1) === str2.charAt(j - 1)) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.substring(longestIdx - longest + 1, longestIdx + 1);
}
#include <vector>
#include <string>
std::string longestCommonSubstring(std::string str1, std::string str2) {
std::vector<std::vector<int>> lengths(str1.size() + 1, std::vector<int>(str2.size() + 1, 0));
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.size(); i++) {
for (int j = 1; j <= str2.size(); j++) {
if (str1[i - 1] == str2[j - 1]) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.substr(longestIdx - longest + 1, longest);
}
public string LongestCommonSubstring(string str1, string str2) {
int[][] lengths = new int[str1.Length + 1][];
for (int i = 0; i < lengths.Length; i++) {
lengths[i] = new int[str2.Length + 1];
}
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.Length; i++) {
for (int j = 1; j <= str2.Length; j++) {
if (str1[i - 1] == str2[j - 1]) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.Substring(longestIdx - longest + 1, longest);
}
func longestCommonSubstring(str1, str2 string) string {
lengths := make([][]int, len(str1)+1)
for i := range lengths {
lengths[i] = make([]int, len(str2)+1)
}
longest := 0
longestIdx := 0
for i := 1; i <= len(str1); i++ {
for j := 1; j <= len(str2); j++ {
if str1[i-1] == str2[j-1] {
lengths[i][j] = lengths[i-1][j-1] + 1
if lengths[i][j] > longest {
longest = lengths[i][j]
longestIdx = i - 1
}
}
}
}
return str1[longestIdx-longest+1 : longestIdx+1]
}
To reverse a string:
string reverseString(string str) {
reverse(str.begin(), str.end());
return str;
}
def reverse_string(str):
return str[::-1]
function reverseString(str) {
return str.split('').reverse().join('');
}
public String reverseString(String str) {
return new StringBuilder(str).reverse().toString();
}
public string ReverseString(string str) {
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
func reverseString(str string) string {
runes := []rune(str)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
This covers some common string algorithms like palindromes, anagrams, longest common substring, and reversal. Strings are core to many domain-specific algorithms as well.
```javascript
function isPalindrome(str) {
const reversed = str.split('').reverse().join('');
return str === reversed;
}
function isAnagram(str1, str2) {
return str1.split('').sort().join('') ===
str2.split('').sort().join('');
}
function longestCommonSubstring(str1, str2) {
const lengths = Array.from({ length: str1.length + 1 }, () => Array(str2.length + 1).fill(0));
let longest = 0;
let longestIdx = 0;
for (let i = 1; i <= str1.length; i++) {
for (let j = 1; j <= str2.length; j++) {
if (str1.charAt(i - 1) === str2.charAt(j - 1)) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.substring(longestIdx - longest + 1, longestIdx + 1);
}
function reverseString(str) {
return str.split('').reverse().join('');
}
// Driver code
console.log(isPalindrome("racecar")); // true
console.log(isAnagram("listen", "silent")); // true
console.log(longestCommonSubstring("ABABC", "BABCAC")); // "BABC"
console.log(reverseString("hello")); // "olleh"
```
```python
from collections import Counter
def is_palindrome(str):
return str == str[::-1]
def is_anagram(str1, str2):
return Counter(str1) == Counter(str2)
def longest_common_substring(str1, str2):
subsequences = [[0] * (len(str2) + 1) for _ in range(len(str1) + 1)]
longest = 0
lcs_idx = (0, 0)
for i in range(1, len(str1) + 1):
for j in range(1, len(str2) + 1):
if str1[i-1] == str2[j-1]:
subsequences[i][j] = 1 + subsequences[i-1][j-1]
if subsequences[i][j] > longest:
longest = subsequences[i][j]
lcs_idx = (i-1, j-1)
return str1[lcs_idx[0]-longest+1:lcs_idx[0]+1]
def reverse_string(str):
return str[::-1]
# Driver code
print(is_palindrome("racecar")) # True
print(is_anagram("listen", "silent")) # True
print(longest_common_substring("ABABC", "BABCAC")) # "BABC"
print(reverse_string("hello")) # "olleh"
```
```java
import java.util.Arrays;
public class Main {
public static boolean isPalindrome(String str) {
String reversed = new StringBuilder(str).reverse().toString();
return str.equals(reversed);
}
public static boolean isAnagram(String str1, String str2) {
char[] charArray1 = str1.toCharArray();
char[] charArray2 = str2.toCharArray();
Arrays.sort(charArray1);
Arrays.sort(charArray2);
return Arrays.equals(charArray1, charArray2);
}
public static String longestCommonSubstring(String str1, String str2) {
int[][] lengths = new int[str1.length() + 1][str2.length() + 1];
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.length(); i++) {
for (int j = 1; j <= str2.length(); j++) {
if (str1.charAt(i-1) == str2.charAt(j-1)) {
lengths[i][j] = lengths[i-1][j-1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i-1;
}
}
}
}
return str1.substring(longestIdx - longest + 1, longestIdx + 1);
}
public static String reverseString(String str) {
return new StringBuilder(str).reverse().toString();
}
public static void main(String[] args) {
System.out.println(isPalindrome("racecar")); // true
System.out.println(isAnagram("listen", "silent")); // true
System.out.println(longestCommonSubstring("ABABC", "BABCAC")); // "BABC"
System.out.println(reverseString("hello")); // "olleh"
}
}
```
```cpp
#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
bool isPalindrome(std::string str) {
std::string reversed = std::string(str.rbegin(), str.rend());
return str == reversed;
}
bool isAnagram(std::string str1, std::string str2) {
std::sort(str1.begin(), str1.end());
std::sort(str2.begin(), str2.end());
return str1 == str2;
}
std::string longestCommonSubstring(std::string str1, std::string str2) {
std::vector<std::vector<int>> lengths(str1.size() + 1, std::vector<int>(str2.size() + 1, 0));
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.size(); i++) {
for (int j = 1; j <= str2.size(); j++) {
if (str1[i - 1] == str2[j - 1]) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.substr(longestIdx - longest + 1, longest);
}
std::string reverseString(std::string str) {
reverse(str.begin(), str.end());
return str;
}
int main() {
std::cout << std::boolalpha << isPalindrome("racecar") << "\n"; // true
std::cout << std::boolalpha << isAnagram("listen", "silent") << "\n"; // true
std::cout << longestCommonSubstring("ABABC", "BABCAC") << "\n"; // "BABC"
std::cout << reverseString("hello") << "\n"; // "olleh"
return 0;
}
```
```csharp
using System;
using System.Linq;
public class Program {
public static bool IsPalindrome(string str) {
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
string reversed = new string(charArray);
return str == reversed;
}
public static bool IsAnagram(string str1, string str2) {
return new string(str1.OrderBy(c => c).ToArray()) ==
new string(str2.OrderBy(c => c).ToArray());
}
public static string LongestCommonSubstring(string str1, string str2) {
int[][] lengths = new int[str1.Length + 1][];
for (int i = 0; i < lengths.Length; i++) {
lengths[i] = new int[str2.Length + 1];
}
int longest = 0;
int longestIdx = 0;
for (int i = 1; i <= str1.Length; i++) {
for (int j = 1; j <= str2.Length; j++) {
if (str1[i - 1] == str2[j - 1]) {
lengths[i][j] = lengths[i - 1][j - 1] + 1;
if (lengths[i][j] > longest) {
longest = lengths[i][j];
longestIdx = i - 1;
}
}
}
}
return str1.Substring(longestIdx - longest + 1, longest);
}
public static string ReverseString(string str) {
char[] charArray = str.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
public static void Main(string[] args) {
Console.WriteLine(IsPalindrome("racecar")); // True
Console.WriteLine(IsAnagram("listen", "silent")); // True
Console.WriteLine(LongestCommonSubstring("ABABC", "BABCAC")); // "BABC"
Console.WriteLine(ReverseString("hello")); // "olleh"
}
}
```
```go
package main
import (
"fmt"
"sort"
"strings"
)
func isPalindrome(str string) bool {
runes := []rune(str)
length := len(runes)
for i := 0; i < length/2; i++ {
runes[i], runes[length-1-i] = runes[length-1-i], runes[i]
}
reversed := string(runes)
return str == reversed
}
func isAnagram(str1, str2 string) bool {
s1 := strings.Split(str1, "")
s2 := strings.Split(str2, "")
sort.Strings(s1)
sort.Strings(s2)
return strings.Join(s1, "") == strings.Join(s2, "")
}
func longestCommonSubstring(str1, str2 string) string {
lengths := make([][]int, len(str1)+1)
for i := range lengths {
lengths[i] = make([]int, len(str2)+1)
}
longest := 0
longestIdx := 0
for i := 1; i <= len(str1); i++ {
for j := 1; j <= len(str2); j++ {
if str1[i-1] == str2[j-1] {
lengths[i][j] = lengths[i-1][j-1] + 1
if lengths[i][j] > longest {
longest = lengths[i][j]
longestIdx = i - 1
}
}
}
}
return str1[longestIdx-longest+1 : longestIdx+1]
}
func reverseString(str string) string {
runes := []rune(str)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func main() {
fmt.Println(isPalindrome("racecar")) // true
fmt.Println(isAnagram("listen", "silent")) // true
fmt.Println(longestCommonSubstring("ABABC", "BABCAC")) // "BABC"
fmt.Println(reverseString("hello")) // "olleh"
}
```
Best Practices and Optimization
Let's delve into the best practices and optimization techniques for handling strings, with insights into memory considerations, common pitfalls, performance optimization, and security.

Memory Considerations: How to handle strings efficiently.
Immutable Strings: In some languages like Java and Python, strings are immutable. This means that modifying a string creates a new object, which can lead to memory overhead. Be aware of this when performing repeated string modifications.
Use StringBuilder/StringBuffer: When concatenating or modifying strings in a loop, consider using
StringBuilderin Java,StringBuilderin C#, or similar constructs in other languages to avoid creating unnecessary string objects.
// Java
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append(i);
}
String result = sb.toString(); // Efficient concatenation
- Avoid Unnecessary Copies: Be cautious with functions that return new string instances, as they can increase memory usage.
Avoiding Common Pitfalls: Common mistakes and how to avoid them.
-
String Equality: Use
.equals()method instead of==to compare strings in Java, as==compares object references, not content.
// Java
String a = "hello";
String b = new String("hello");
boolean isEqual = a.equals(b); // true
- Proper Encoding/Decoding: Ensure proper encoding and decoding when reading or writing strings to avoid character corruption.
Optimizing String Operations: Tips for writing performant code.
-
Prefer
indexOfOver Regular Expressions: When searching for simple substrings, prefer usingindexOfor similar methods over regular expressions as they are generally faster.
// JavaScript
var str = "Welcome to Earth!";
var found = str.indexOf("Earth") !== -1; // true
- Use Compile-Time Constants: When possible, use compile-time constants or literals to optimize performance.
Secure String Handling: Security considerations in string manipulation.
- Avoid Injection Vulnerabilities: Be cautious when constructing SQL queries or other code structures from user input. Use prepared statements or parameterized queries to avoid SQL injection.
// Java
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
stmt.setString(1, userName);
ResultSet rs = stmt.executeQuery();
Sanitize User Input: Always sanitize user input when it will be rendered on a web page to prevent Cross-Site Scripting (XSS) attacks.
Handle Sensitive Data Carefully: When dealing with sensitive information like passwords, consider using specialized libraries for handling and storing such data, and avoid logging or unnecessarily copying these strings.
By adhering to these best practices and optimization strategies, you can write efficient, secure, and robust string manipulation code. Understanding these principles will not only enhance your coding skills but also make you stand out in technical interviews and professional development.

One Pager Cheat Sheet
One Pager Cheat Sheet
- The article stresses the importance of string manipulation in software development, considering it a vital skill in processing human-readable data, and highlights its significance in coding interviews; it then introduces the intended comprehensive guide which aims to teach techniques and best practices for string manipulation, aiding both seasoned programmers and beginners to become more effective professionals.
- A string is a
data typein programming that represents a sequence of characters, which can beimmutable(cannot be changed once created, as in Java and Python) ormutable(can be modified, as in C++); basic string operations includedeclaring and initializing strings,finding the length of a string,concatenating strings, andextracting parts of a stringthrough slicing or finding a substring, forming the foundation for complex string manipulation tasks. - This section covers fundamental string operations including
concatenation(combining strings), extractingsubstrings, finding thelengthof a string,comparingstrings, converting characters'case, andtrimmingandpaddingstrings, featuring examples in multiple programming languages such asJavaScript,Python,Java,C++, andGo. - The passage discusses how to search for substrings and characters within strings in various programming languages (JavaScript, Java, Python, Go, C++) using
indexOf,contains,find,Index, andincludesmethods, it also explains pattern matching usingregular expressions (regex), and demonstrates globbing with wildcard characters like* and ?for matching file types. - This document provides code snippets in several programming languages for four common string manipulation algorithms: checking if a string is a
palindrome, checking if two strings areanagrams, finding thelongest common substringof two strings, andreversinga string. - The article discusses the best practices and optimization techniques for managing strings, touching on memory considerations, avoiding common pitfalls, performance optimization, and secure string handling. These include understanding immutable strings and employing
StringBuilderclasses for efficient string modification, cautious use of functions to avoid unnecessary copies of strings, using.equals()for string equality rather than==, ensuring proper encoding/decoding of strings, preferential use ofindexOfover regular expressions, using compile-time constants, avoiding SQL injection vulnerabilities through prepared statements, sanitizing user input, and secure handling of sensitive data.