
String manipulation is one of the most heavily tested concepts in the AP Computer Science A FRQ section. Students must know how to process characters, analyze substrings, validate formats, and build new strings using loops and conditions.
This page provides exam-style FRQ practice questions designed to strengthen your string-processing logic.
Why Practice String FRQs?
AP CSA often includes free-response problems requiring:
- substring extraction
- counting patterns
- validating input formats
- scanning through characters
- building new strings with rules
- solving text-based algorithm problems
Mastering these string skills dramatically improves FRQ performance.
How to Use This Page
- Attempt each problem before checking the solution
- Compare your logic with the sample answer
- Study the Common Mistakes to avoid scoring loss
- Re-practice the problem until you can solve it quickly
- Use these as real exam warm-ups
FRQ 1 — Count Vowels
Write countVowels(String s) that returns how many vowels
(a, e, i, o, u) appear in the string. Ignore case.
“Computer” → 3
- Convert the string to lowercase
- Traverse each character
- Check membership in
"aeiou"
public int countVowels(String s) {
int count = 0;
String low = s.toLowerCase();
for (int i = 0; i < low.length(); i++) {
if ("aeiou".indexOf(low.charAt(i)) != -1) {
count++;
}
}
return count;
}
- Ignoring uppercase vowels
- Checking only one vowel
- Using
==for String comparison
FRQ 2 — Remove All Digits
Write removeDigits(String s) that returns a new string
with all digits removed.
"a1b2c3d4" → "abcd"
- Traverse the string
- Append only non-digit characters
- Use
Character.isDigit()
public String removeDigits(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
result.append(s.charAt(i));
}
}
return result.toString();
}
- Using
+inside a loop - Returning
nullinstead of empty string - Incorrect digit detection
FRQ 3 — Reverse a String
Write reverseString(String s) that returns the reversed string.
"java" → "avaj"
- Traverse from the last index to 0
- Append characters to a new string
public String reverseString(String s) {
StringBuilder rev = new StringBuilder();
for (int i = s.length() - 1; i >= 0; i--) {
rev.append(s.charAt(i));
}
return rev.toString();
}
- Off-by-one loop errors
- Traversing forward instead of backward
FRQ 4 — Count Words
Assume words are separated by a single space. Return the number of words in the string.
"AP Computer Science" → 3
- Count spaces
- Words = spaces + 1
public int countWords(String s) {
if (s.length() == 0) return 0;
int count = 1;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
count++;
}
}
return count;
}
- Not handling empty string
- Counting multiple spaces as multiple words
FRQ 5 — Find the Longest Word
Write longestWord(String sentence) that returns the longest word.
Assume words are separated by spaces.
"I love programming in Java" → "programming"
- Split the sentence using spaces
- Track the longest word
public String longestWord(String sentence) {
String[] words = sentence.split(" ");
String longest = "";
for (String w : words) {
if (w.length() > longest.length()) {
longest = w;
}
}
return longest;
}
- Using
>=instead of> - Not handling empty sentence
FRQ 6 — Remove Vowels
Write removeVowels(String s) that removes all vowels
(case-insensitive) from the string.
"Computer" → "Cmptr"
- Traverse each character
- Convert to lowercase for checking
- Append only non-vowel characters
public String removeVowels(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = Character.toLowerCase(s.charAt(i));
if ("aeiou".indexOf(c) == -1) {
result.append(s.charAt(i));
}
}
return result.toString();
}
- Forgetting uppercase vowels
- Removing original character case
FRQ 7 — Check Palindrome
Write isPalindrome(String s) that returns true
if the string reads the same forwards and backwards.
"level" → true
- Use two pointers from start and end
- Compare characters
- Stop early if mismatch occurs
public boolean isPalindrome(String s) {
int left = 0;
int right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
- Incorrect pointer movement
- Comparing wrong indices
FRQ 8 — Count Uppercase Letters
Write countUppercase(String s) that returns
the number of uppercase letters in the string.
"ApCSa" → 2
- Traverse the string
- Use
Character.isUpperCase()
public int countUppercase(String s) {
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (Character.isUpperCase(s.charAt(i))) {
count++;
}
}
return count;
}
- Manual ASCII comparisons
- Counting lowercase letters
FRQ 9 — Count Substring Occurrences
Write countOccurrences(String s, String sub)
that counts overlapping occurrences of sub.
"aaaa", "aa" → 3
- Slide a window of length
sub.length() - Move one index at a time
- Compare substrings
public int countOccurrences(String s, String sub) {
int count = 0;
for (int i = 0; i <= s.length() - sub.length(); i++) {
if (s.substring(i, i + sub.length()).equals(sub)) {
count++;
}
}
return count;
}
- Using
==instead ofequals() - Loop boundary errors
- Missing overlapping matches
FRQ 10 — Validate ID Format
A valid ID has 2 letters followed by 4 digits.
Return true if the format is valid.
"AB1234" → true
- Check string length
- Validate letters and digits separately
public boolean isValidID(String id) {
if (id.length() != 6) return false;
if (!Character.isLetter(id.charAt(0)) ||
!Character.isLetter(id.charAt(1))) {
return false;
}
for (int i = 2; i < 6; i++) {
if (!Character.isDigit(id.charAt(i))) {
return false;
}
}
return true;
}
- Not checking string length first
- Accessing invalid indices
FRQ 11 — Remove Extra Spaces
Replace multiple consecutive spaces with a single space.
"AP Computer Science" → "AP Computer Science"
- Traverse characters one by one
- Append character if previous is not a space
public String removeExtraSpaces(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (i == 0 || s.charAt(i) != ' ' || s.charAt(i - 1) != ' ') {
result.append(s.charAt(i));
}
}
return result.toString();
}
- Using split() unnecessarily
- Not handling leading spaces
FRQ 12 — Extract Digits
Return a string containing only digits from the input string.
"ab12cd34" → "1234"
- Traverse each character
- Append digits only
public String extractDigits(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (Character.isDigit(s.charAt(i))) {
result.append(s.charAt(i));
}
}
return result.toString();
}
- Returning an integer instead of a string
- Manual digit comparison
FRQ 13 — Longest Consecutive Character
Return the character with the longest consecutive repetition. Assume the string is non-empty.
"aaabbccccd" → 'c'
- Track current streak length
- Track longest streak and character
public char longestStreak(String s) {
char best = s.charAt(0);
int bestCount = 1;
int count = 1;
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == s.charAt(i - 1)) {
count++;
if (count > bestCount) {
bestCount = count;
best = s.charAt(i);
}
} else {
count = 1;
}
}
return best;
}
- Not resetting count
- Not updating best character
FRQ 14 — Compress String
Compress consecutive characters using counts.
"aaabbc" → "a3b2c1"
- Count consecutive characters
- Append character followed by count
public String compress(String s) {
StringBuilder result = new StringBuilder();
int count = 1;
for (int i = 1; i <= s.length(); i++) {
if (i < s.length() && s.charAt(i) == s.charAt(i - 1)) {
count++;
} else {
result.append(s.charAt(i - 1)).append(count);
count = 1;
}
}
return result.toString();
}
- Missing the last character group
- Loop boundary errors
FRQ 15 — Mask Email Username
Mask all characters of the email username except the first and last character.
"john.doe@gmail.com" → "j*****e@gmail.com"
- Separate username and domain
- Replace middle characters with '*'
public String maskEmail(String email) {
int at = email.indexOf('@');
String user = email.substring(0, at);
String domain = email.substring(at);
if (user.length() <= 2) return email;
StringBuilder masked = new StringBuilder();
masked.append(user.charAt(0));
for (int i = 1; i < user.length() - 1; i++) {
masked.append('*');
}
masked.append(user.charAt(user.length() - 1));
return masked.toString() + domain;
}
- Masking the domain part
- Not handling short usernames
FRQ Strategy Tips for Strings (AP CSA)
- Always clarify assumptions before coding
- Prefer index-based loops over enhanced for-loops
- Use StringBuilder when building new strings
- Watch loop boundaries carefully
- Partial credit is awarded for correct logic even if minor bugs exist
Related FRQ Pages
- Arrays – FRQ Practice
- ArrayList – FRQ Practice
- 2D Arrays – FRQ Practice
- Classes & Objects – FRQ Practice
- Mixed FRQs
- Mock FRQ Sets
Need Structured Help With AP Computer Science A?
If you want guided, one-on-one support for AP Computer Science A—including
FRQs, MCQs, debugging, and exam strategy—you can explore my dedicated
tutoring program here:
AP Computer Science A tutoring support
https://www.javatutoronline.com/training-courses/ap-computer-science-tutor/
Ideal for students targeting a score of 4 or 5 on the AP CSA exam.