Algorithms
Character Indexing
Programming
Coding Techniques
Data Structures

Algorithm Printing the correct index for the character sequence

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Printing the correct index for a character sequence usually means finding where a substring appears inside a larger string. The hard part is rarely the loop itself. The real problems are off by one mistakes, overlapping matches, and unclear rules about whether indexing starts at zero or one.

Define What “Correct Index” Means

Before writing code, decide which index you want to print. Most programming languages use zero-based indexing, so the first character of "banana" is at index 0, not 1. If the sequence appears more than once, you also need to decide whether you want the first match only or every match.

For example, searching for "ana" in "banana" can produce:

  • first match only: 1
  • all matches with overlap allowed: 1 and 3
  • all matches without overlap: 1

That choice changes the algorithm. A loop that advances by one character after each check will find overlapping matches. A loop that jumps by the pattern length will not.

A Simple Scan That Prints Every Match

The most direct solution is to examine every possible starting position and compare the slice against the target sequence. This runs in O(n * m) time for text length n and pattern length m, which is often fine for small inputs.

python
1from typing import List
2
3
4def find_indices(text: str, pattern: str) -> List[int]:
5    if pattern == "":
6        raise ValueError("pattern must not be empty")
7
8    matches: List[int] = []
9    last_start = len(text) - len(pattern)
10
11    for start in range(last_start + 1):
12        if text[start:start + len(pattern)] == pattern:
13            matches.append(start)
14
15    return matches
16
17
18print(find_indices("banana", "ana"))
19print(find_indices("abracadabra", "abra"))
text
[1, 3]
[0, 7]

This version is easy to reason about because each possible start position is checked exactly once. It is also a good baseline for tests because more advanced algorithms should produce the same indices.

Printing Indices While Iterating Characters

Sometimes you are asked to print the index as the algorithm runs instead of collecting it first. In that case, keep the same scanning logic and print the current start when a match is found.

python
1
2def print_indices(text: str, pattern: str) -> None:
3    if pattern == "":
4        raise ValueError("pattern must not be empty")
5
6    for start in range(len(text) - len(pattern) + 1):
7        if text[start:start + len(pattern)] == pattern:
8            print(f"match at index {start}")
9
10
11print_indices("mississippi", "issi")

If your assignment expects one-based indexing for human-readable output, convert only at the print step. Internally, stay with zero-based values because slices and loops are naturally expressed that way.

python
print(f"match at position {start + 1}")

That keeps the algorithm correct while adapting the presentation format.

When Performance Matters

For very large inputs, repeated slicing becomes expensive. In those cases, use a string-search algorithm such as Knuth-Morris-Pratt or rely on the language runtime if it exposes efficient search primitives. In Python, repeated calls to str.find can be a practical middle ground.

python
1
2def find_with_builtin(text: str, pattern: str) -> list[int]:
3    if pattern == "":
4        raise ValueError("pattern must not be empty")
5
6    indices: list[int] = []
7    start = 0
8
9    while True:
10        index = text.find(pattern, start)
11        if index == -1:
12            break
13        indices.append(index)
14        start = index + 1
15
16    return indices
17
18
19print(find_with_builtin("banana", "ana"))

Notice the start = index + 1. Advancing by one keeps overlapping matches. If you change that line to index + len(pattern), overlapping matches disappear.

Common Pitfalls

The most common bug is looping too far or not far enough. If the last valid starting position is len(text) - len(pattern), then the range must include that value. In Python that means range(len(text) - len(pattern) + 1). Missing the + 1 silently drops a valid match at the end of the string.

Another frequent mistake is forgetting to define behavior for an empty pattern. Some libraries treat an empty pattern as matching everywhere, but many interview-style problems expect it to be rejected. Pick one behavior and document it.

Unicode can also surprise you. If the input contains composed characters, the visual symbol a user sees may not correspond to a single code point. If your system works with user-visible characters instead of raw code points, normalize the text before searching.

Finally, do not mix one-based and zero-based indices in the same algorithm. Compute with one convention and convert only at the boundary where output is displayed.

Summary

  • Define whether you want the first match, all matches, or only non-overlapping matches.
  • Use zero-based indices internally even if the final output is one-based.
  • A direct slice comparison loop is simple and correct for many inputs.
  • Built-in search functions can reduce complexity in real code.
  • Most indexing bugs come from off by one errors and unclear empty-pattern rules.

Course illustration
Course illustration

All Rights Reserved.