Lesson 2.10: Implementing String Algorithms
Lesson 2.10: Implementing String Algorithms
What You'll Learn
- 2.10.A: Develop code for standard string algorithms. (EK 2.10.A.1)
- Use
substring(start, end)to extract and compare substrings. - Identify the correct loop bound for length-k substring traversal.
- Find if substrings have a property; count substrings meeting a criterion.
- Create a reversed String; build new Strings from parts of the original.
Key Vocabulary
| Term | Definition |
|---|---|
| String traversal | Processing a String character by character or substring by substring using a loop. The loop index is used with charAt(i) or substring(i, i+k). |
| charAt(i) | Returns the char at 0-based index i. Best for single-character checks. Throws StringIndexOutOfBoundsException if i < 0 or i >= length(). |
| substring(start, end) | Returns a new String containing characters from index start up to but not including index end. Most heavily tested String method on the AP exam. (EK 2.10.A.1) |
| substring(start) | Returns a new String from index start to the end of the string. Equivalent to substring(start, length()). |
| indexOf(str) | Returns the index of the first occurrence of str, or -1 if not found. Useful for substring search algorithms. |
| length() | Returns the number of characters in the String. Valid indices are 0 through length()-1. |
| equals(other) | Compares String content (not memory address). Always use .equals(), never ==, to compare String values. |
The String API: What AP Actually Tests
The AP CSA exam tests String manipulation heavily — it appears in almost every FRQ set. The most critical method to master is substring(start, end), which appears far more often than charAt() in both MCQs and FRQs. Understanding exactly which characters are included (start inclusive, end exclusive) is the single most tested String fact.
CED Connection (EK 2.10.A.1)
The three standard string algorithms: (1) find if one or more substrings have a particular property, (2) determine the number of substrings that meet specific criteria, (3) create a new string with the characters reversed. All three appear regularly in FRQ problems and require substring manipulation.
Critical: substring(start, end) Indexing
String s = "computer"; // 01234567 ← 0-based indices s.substring(0, 3) → "com" // chars at 0,1,2 (NOT 3) s.substring(3, 6) → "put" // chars at 3,4,5 (NOT 6) s.substring(6) → "er" // chars at 6,7 to end s.substring(0, s.length()) → "computer" // full string // Rule: substring(a, b) gives b - a characters // starting at index a, stopping BEFORE index b
The Standard String Methods
| Method | Returns / Notes |
|---|---|
s.length() |
int — number of chars. Valid indices: 0 to length()-1. |
s.substring(a, b) |
String — chars from index a up to but NOT including b. Length = b-a. |
s.substring(a) |
String — chars from index a to end. Same as substring(a, length()). |
s.charAt(i) |
char — single character at index i. Use == for comparison. |
s.indexOf(t) |
int — first index where t appears, or -1 if not found. |
s.equals(t) |
boolean — true if same content. Never use == on String objects. |
s.equalsIgnoreCase(t) |
boolean — same as equals() but ignores case. |
Algorithm 1: Find if Substrings Have a Property
Scan a String to find whether any substring satisfies a condition. When checking substrings of length k, loop from 0 to s.length() - k inclusive, extracting each with substring(i, i+k). Use .equals() to compare substring results.
Worked Example — Does String Contain a Target Substring?
// Does s contain the substring "cat"?
public static boolean containsCat(String s) {
for (int i = 0; i <= s.length() - 3; i++) {
if (s.substring(i, i + 3).equals("cat")) {
return true;
}
}
return false;
}
System.out.println(containsCat("concatenate")); // true (index 3)
System.out.println(containsCat("dog")); // false
// Or just use indexOf:
System.out.println(s.indexOf("cat") >= 0); // true if found
Worked Example — Does Any Length-2 Substring Appear Twice?
// Check if any 2-char substring appears more than once
public static boolean hasRepeat(String s) {
for (int i = 0; i <= s.length() - 2; i++) {
String sub = s.substring(i, i + 2);
for (int j = i + 1; j <= s.length() - 2; j++) {
if (s.substring(j, j + 2).equals(sub)) {
return true; // found duplicate
}
}
}
return false;
}
System.out.println(hasRepeat("abcab")); // true ("ab" appears at 0 and 3)
System.out.println(hasRepeat("abcde")); // false
Algorithm 2: Count Substrings Meeting a Criterion
Count occurrences of a target substring, or count substrings satisfying a condition. Initialize a counter to 0 before the loop, increment whenever the criterion is met.
Worked Example — Count Occurrences of a Substring
public static int countSubstring(String s, String target) {
int count = 0;
int k = target.length();
for (int i = 0; i <= s.length() - k; i++) {
if (s.substring(i, i + k).equals(target)) {
count++;
}
}
return count;
}
System.out.println(countSubstring("banana", "an")); // 2
System.out.println(countSubstring("aabaa", "aa")); // 2 (overlapping: 0 and 3)
System.out.println(countSubstring("hello", "xyz")); // 0
Worked Example — Count Substrings With a Property
// Count length-3 substrings that start with a vowel
public static int countVowelStart(String s) {
int count = 0;
String vowels = "aeiouAEIOU";
for (int i = 0; i <= s.length() - 3; i++) {
char first = s.charAt(i); // charAt for single char check
if (vowels.indexOf(first) >= 0) {
count++;
}
}
return count;
}
System.out.println(countVowelStart("education")); // 3 ("edu","duc","uca")... check:
// i=0: s.charAt(0)='e' → vowel, count=1
// i=1: 'd' → not, count stays
// i=2: 'u' → vowel, count=2
// ... actual result depends on full string
Algorithm 3: Reverse a String
Build a reversed copy using substring. The cleanest approach: loop from the last index down to 0, extracting each single-character substring and appending.
Worked Example — Reverse Using substring
// Method 1: substring(i, i+1) to extract each char as String
public static String reverse(String s) {
String result = "";
for (int i = s.length() - 1; i >= 0; i--) {
result += s.substring(i, i + 1); // single-char substring
}
return result;
}
// Method 2: prepend approach with substring
public static String reverse2(String s) {
String result = "";
for (int i = 0; i < s.length(); i++) {
result = s.substring(i, i + 1) + result; // prepend each char
}
return result;
}
System.out.println(reverse("hello")); // "olleh"
System.out.println(reverse2("java")); // "avaj"
// charAt version also valid — charAt returns char not String:
// result = s.charAt(i) + result; // char + String concatenation
Building New Strings from Parts
Many AP FRQ problems ask you to build a new String by selecting, rearranging, or transforming parts of the original. The key tool is always substring(start, end) to extract ranges of characters.
Worked Example — Remove All Spaces
public static String removeSpaces(String s) {
String result = "";
for (int i = 0; i < s.length(); i++) {
if (!s.substring(i, i + 1).equals(" ")) {
result += s.substring(i, i + 1);
}
}
return result;
}
System.out.println(removeSpaces("hello world")); // "helloworld"
System.out.println(removeSpaces("a b c")); // "abc"
Worked Example — Replace Every Other Character
// Replace every character at an odd index with '*'
public static String maskOdd(String s) {
String result = "";
for (int i = 0; i < s.length(); i++) {
if (i % 2 == 0) {
result += s.substring(i, i + 1); // keep even-indexed chars
} else {
result += "*"; // replace odd-indexed chars
}
}
return result;
}
System.out.println(maskOdd("computer")); // "c*m*u*e*"
Using indexOf for Substring Search
indexOf(target) returns the starting index of the first occurrence of target, or -1 if not found. It is the most direct way to check if a substring exists and to find its position.
Worked Example — indexOf Patterns
String s = "programming";
// Does s contain "gram"?
System.out.println(s.indexOf("gram") >= 0); // true (index 3)
System.out.println(s.indexOf("gram")); // 3
// Does s contain "xyz"?
System.out.println(s.indexOf("xyz") >= 0); // false
System.out.println(s.indexOf("xyz")); // -1
// Extract everything after the first space
String sentence = "Hello World";
int spaceIdx = sentence.indexOf(" ");
String afterSpace = sentence.substring(spaceIdx + 1);
System.out.println(afterSpace); // "World"
AP Trap: substring End Index is EXCLUSIVE
s.substring(2, 5) returns chars at indices 2, 3, 4 — NOT 5. The end index is always excluded. The number of characters returned = end - start. The most common FRQ error is using the last index you want instead of last+1.
AP Trap: Loop Bound for Length-k Substrings
To check every substring of length k, the loop condition must be i <= s.length() - k, not i < s.length(). With the wrong bound, substring(i, i+k) throws StringIndexOutOfBoundsException on the last iteration(s).
// String "hello" (length 5), substrings of length 3
// Valid start indices: 0, 1, 2 (giving "hel","ell","llo")
// Bound: i <= 5 - 3 = 2 → i <= s.length() - k
for (int i = 0; i <= s.length() - 3; i++) {
System.out.println(s.substring(i, i + 3));
}
AP Trap: charAt vs substring Return Type
charAt(i) returns a primitive char — compare with ==. substring(i, i+1) returns a String object — compare with .equals(). Mixing them up is a guaranteed FRQ error. Both extract one character, but the type is different.
Real-World Connection
Substring manipulation is at the core of how computers handle text. Every search engine uses substring matching to find queries in documents. Text editors use substring extraction to implement cut/copy/paste. URL parsers use indexOf() to split addresses into protocol, domain, and path. DNA sequencing software matches gene patterns using substring search across billions of characters. The standard string algorithms in EK 2.10.A.1 are the foundation of all text-processing software ever written.
Summary
- substring(start, end): most-tested String method. Start inclusive, end exclusive. Length = end - start.
- substring(start): from start to end of String.
-
Length-k traversal bound:
i <= s.length() - k. Wrong bound → exception. - Property check: loop + substring extraction + .equals() or condition. Return true when found. (EK 2.10.A.1)
- Count: counter += 1 each time condition met. (EK 2.10.A.1)
- Reverse: build result String traversing back-to-front or prepending each substring. (EK 2.10.A.1)
-
indexOf: returns first index of target or -1. Use
>= 0to check existence. - charAt returns char (use ==); substring returns String (use .equals()).
Practice Questions
s.substring(2, 5) return when s = "abcdefg"?"abc"
"cde"
"bcde"
"cdef"
s = "hello"?public static String mystery(String s) {
String r = "";
for (int i = s.length() - 1; i >= 0; i--) {
r += s.substring(i, i + 1);
}
return r;
}
"hello"
"olleh"
"h"
"o"
s.for (int i = 0; i < s.length(); i++) {
String sub = s.substring(i, i + 3);
System.out.println(sub);
}
charAt(i) instead of substring
i <= s.length() - 3
substring(i, i+3) should be substring(i, i+2)
substring(i, i+3) tries to access past the end, throwing StringIndexOutOfBoundsException. Correct bound: i <= s.length() - 3.s = "abcabc" and target = "bc"?public static int countOccur(String s, String target) {
int count = 0;
int k = target.length();
for (int i = 0; i <= s.length() - k; i++) {
if (s.substring(i, i + k).equals(target))
count++;
}
return count;
}
s = "Hello World"?int idx = s.indexOf(" ");
String result = s.substring(idx + 1);
System.out.println(result);
"Hello"
" World"
"World"
"Hello World"
s with the first and last characters swapped?String r = s.substring(s.length()-1) + s.substring(1, s.length()-1) + s.substring(0,1);
String r = s.charAt(s.length()-1) + s.substring(1, s.length()-1) + s.charAt(0);
String r = s.substring(s.length()-1,s.length()) + s.substring(1,s.length()-1) + s.substring(0,1);
String r = s.substring(s.length()) + s.substring(1,s.length()-1) + s.substring(0,1);
String s = "programming";
String result = "";
for (int i = 0; i < s.length() - 1; i += 2) {
result += s.substring(i, i + 2);
}
System.out.println(result);
"programming"
"prga"
"prgamig"
"prgramng"
s?s.substring(s.length() - 3, s.length())
s.substring(s.length() - 3)
s.substring(s.length() - 3, s.length() + 1)
After the code runs, what is the value of ?
Mastery: Implementing String Algorithms
s = "racecar"?public static boolean isPalin(String s) {
for (int i = 0; i < s.length() / 2; i++) {
String front = s.substring(i, i + 1);
String back = s.substring(s.length()-1-i, s.length()-i);
if (!front.equals(back)) return false;
}
return true;
}
false
true
false — middle char not handled
s = "adbc"?int count=0; for(int i=0;i
int count=0;
for(int i=0;i<=s.length()-2;i++){
String sub=s.substring(i,i+2);
if(sub.substring(0,1).compareTo(sub.substring(1,2))<0) count++;
}
return count;
int count=0; for(int i=0;i
s = "mississippi"?public static int countTarget(String s) {
int count = 0;
for (int i = 0; i <= s.length() - 2; i++) {
if (s.substring(i, i + 2).equals("ss"))
count++;
}
return count;
}
substring(a,b) returns b-a characters II. Loop bound for length-k substrings is i < s.length()-k III. indexOf(t) returns -1 when t is not foundWhich are TRUE?
i <= s.length()-k (less than or EQUAL), not strictly less than. Using strict less-than misses the last valid starting position.Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]