Two Pointers - Word Abbreviation

Estimated Time: 2 hours
Tech Stack: Java
Keywords: Data Structure - Algorithms
Experience Level: Beginner - Advanced
Category: TwoPointers
Skill: Parsing Numbers; Using Two Pointers on two different strings.

408. Valid Word Abbreviation

A string can be abbreviated by replacing any number of non-adjacent, non-empty substrings with their lengths. The lengths should not have leading zeros. For example, a string such as "substitution" could be abbreviated as (but not limited to):

  • "s10n" ("s ubstitutio n")

  • "sub4u4" ("sub stit u tion")

  • "12" ("substitution")

  • "su3i1u2on" ("su bst i t u ti on")

  • "substitution" (no substrings replaced)

  • The following are not valid abbreviations:

  • "s55n" ("s ubsti tutio n", the replaced substrings are adjacent)

  • "s010n" (has leading zeros)

  • "s0ubstitution" (replaces an empty substring)

Given a string word and an abbreviation abbr, return whether the string matches the given abbreviation. A substring is a contiguous non-empty sequence of characters within a string.

Example 1:

Input: word = "internationalization", abbr = "i12iz4n" Output: true Explanation: The word "internationalization" can be abbreviated as "i12iz4n" ("i nternational iz atio n").

Example 2:

Input: word = "apple", abbr = "a2e" Output: false Explanation: The word "apple" cannot be abbreviated as "a2e".

Constraints:

1 <= word.length <= 20 word consists of only lowercase English letters. 1 <= abbr.length <= 10 abbr consists of lowercase English letters and digits. All the integers in abbr will fit in a 32-bit integer.

Solution:

package TwoPointers;

public class dAbbreviationValidator {

    public static boolean validWordAbbreviation(String word, String abbr) {
        int i = 0; // pointer for word
        int j = 0; // pointer for abbr

        while (i < word.length() && j < abbr.length()) {
            char current = abbr.charAt(j);

            // ๐ŸŸ  Case 1: Digit in abbreviation
            if (Character.isDigit(current)) {
                if (current == '0') {
                    return false; // ๐Ÿšซ Leading zero
                }

                int num = 0;
                while (j < abbr.length() && Character.isDigit(abbr.charAt(j))) {
                    num = num * 10 + (abbr.charAt(j) - '0');
                    j++;
                }

                i += num; // Skip characters in word
            }

            // ๐ŸŸข Case 2: Letter in abbreviation
            else {
                if (i >= word.length() || word.charAt(i) != current) {
                    return false; // ๐Ÿšซ Mismatch
                }
                i++;
                j++;
            }
        }

        // โœ… Both pointers must reach the end
        return i == word.length() && j == abbr.length();
    }

    public static void main(String[] args) {
        System.out.println(validWordAbbreviation("internationalization", "i12iz4n")); // true
        System.out.println(validWordAbbreviation("apple", "a2e")); // false
        System.out.println(validWordAbbreviation("substitution", "s10n")); // true
        System.out.println(validWordAbbreviation("substitution", "s010n")); // false (leading zero)
        System.out.println(validWordAbbreviation("substitution", "s0ubstitution")); // false (empty substring)
    }
}


๐Ÿ” Class Header

package AdHoc;

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œThis class is part of the TwoPointers package.โ€

๐Ÿ“˜ Explanation:

Organizes your code inside a named package โ€” like putting a file in a folder.


public class AbbreviationValidator {

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œThis is a public class named dAbbreviationValidator.โ€

๐Ÿ“˜ Explanation:

Defines the class where your logic and main method will live.


๐Ÿง  Method Declaration

public static boolean validWordAbbreviation(String word, String abbr) {

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œDefine a public static method called validWordAbbreviation that takes a word and an abbreviation, and returns true or false.โ€

๐Ÿ“˜ Explanation:

This method checks if abbr is a valid abbreviation for word.


๐Ÿงฎ Pointers Initialization

int i = 0; // pointer for word
int j = 0; // pointer for abbr

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œCreate two integer pointers i and j, both starting at zero.โ€

๐Ÿ“˜ Explanation:

i tracks position in word, j tracks position in abbr.


๐Ÿ” Loop Through Characters

while (i < word.length() && j < abbr.length()) {

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œWhile both pointers are within bounds of their strings, keep looping.โ€

๐Ÿ“˜ Explanation:

Loop continues as long as we havenโ€™t finished parsing both strings.


๐Ÿ”Ž Get the Current Abbreviation Character

char current = abbr.charAt(j);

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œGet the current character in abbr at position j.โ€

๐Ÿ“˜ Explanation:

Stores the character to decide if itโ€™s a letter or digit.


๐Ÿ”  If the Current Character is a Digit

if (Character.isDigit(current)) {

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œIf the character is a digit...โ€

๐Ÿ“˜ Explanation:

Abbreviations can include numbers that tell us how many characters to skip in the word.


๐Ÿ›‘ Check for Leading Zero

if (current == '0') {
    return false;
}

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œIf the digit is zero, return false.โ€

๐Ÿ“˜ Explanation:

Leading zeros like 01, 007 are not valid โ€” skip is not allowed to begin with zero.


๐Ÿ”ข Parse the Number

int num = 0;
while (j < abbr.length() && Character.isDigit(abbr.charAt(j))) {
    num = num * 10 + (abbr.charAt(j) - '0');
    j++;
}

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œWhile weโ€™re still seeing digits, build the full number and move j forward.โ€

๐Ÿ“˜ Explanation:

This handles multi-digit numbers (e.g., "12"), and moves the j pointer past all digits.

๐Ÿงช Walkthrough 1: Parsing "15"

Let's say abbr = "a15b" and we're starting at index j = 1.

Stepabbr.charAt(j)abbr.charAt(j) - '0'num = num * 10 + digitnum valuej
1'1'10 * 10 + 112
2'5'51 * 10 + 5153
3'b'โŒ not a digitโ€”end loop

โœ… Final result: num = 15

โฉ Skip Characters in Word

i += num;

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œMove the word pointer forward by that number.โ€

๐Ÿ“˜ Explanation:

You're skipping over num characters in the original word โ€” as instructed by the abbreviation.


๐Ÿ”ค If It's a Letter

} else {
    if (i >= word.length() || word.charAt(i) != current) {
        return false;
    }
    i++;
    j++;
}

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œOtherwise, if itโ€™s a letter, compare it with the current letter in word.โ€

๐Ÿ“˜ Explanation:

If the letters donโ€™t match, itโ€™s invalid. If they do, move both pointers forward.


โœ… Final Check

return i == word.length() && j == abbr.length();

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œReturn true only if both pointers reached the end of their strings.โ€

๐Ÿ“˜ Explanation:

Weโ€™re only done if both strings are fully parsed โ€” no leftovers.


๐Ÿงช Test Code

public static void main(String[] args) {

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œMain method โ€” this is where the program starts.โ€

๐Ÿ“˜ Explanation:

This is your test area to run the validator with different inputs.


System.out.println(validWordAbbreviation("internationalization", "i12iz4n")); // true
System.out.println(validWordAbbreviation("apple", "a2e")); // false
System.out.println(validWordAbbreviation("substitution", "s10n")); // true
System.out.println(validWordAbbreviation("substitution", "s010n")); // false
System.out.println(validWordAbbreviation("substitution", "s0ubstitution")); // false

๐Ÿ—ฃ๏ธ Say it out loud:

โ€œCall the method with different test cases and print the results.โ€

๐Ÿ“˜ Explanation:

Validates both correct and incorrect abbreviations to confirm your logic works as expected.


โœ… Output

true
false
true
false
false

โœ๏ธ Challenges in the Word Abbreviation Problem

๐Ÿง  You're doing something that few learners take the time to do โ€” extracting wisdom from experience. Letโ€™s now reflect on the challenges of the Word Abbreviation Validation problem.

๐Ÿ” Challenge๐Ÿ’ฌ Why Itโ€™s Tricky
1. Parsing numbers from a stringYou have to manually parse digits into full numbers ("12" โ†’ 12) without using Integer.parseInt() and handle them character by character.
2. Dealing with leading zerosA tricky constraint: abbreviations like "s010n" are invalid. You need to explicitly check for '0' and reject it early.
3. Using two pointers on two different stringsYouโ€™re walking two strings at the same time (word[i] and abbr[j]), and syncing them correctly is harder than it looks, especially with skips involved.
4. Skipping characters based on a parsed numberOnce you parse a number from abbr, you skip that many characters in word. If you're not careful, youโ€™ll go out of bounds or mismatch letters.
5. Comparing letters correctlyWhen not looking at a digit, you're expected to match the character in abbr with word. A mismatch at any position should immediately return false.
6. Edge case handling (empty abbreviation, k = 0, etc.)Handling very short inputs, all-digit abbreviations (e.g., "10"), or full word abbreviations requires precise thinking.
7. Returning false on invalid structureNot all abbreviation attempts are valid โ€” your algorithm needs to catch violations without false positives.
8. Knowing when both pointers should end togetherA valid abbreviation must consume the full word and abbr. If one finishes early, itโ€™s invalid โ€” thatโ€™s easy to forget.

๐Ÿง  Bonus Challenge: Manual character-by-character parsing

Parsing a number from a string without built-in parsing teaches you how characters and digits relate via ASCII math, which is an advanced beginner skill you now have!


โœ… Summary

ConceptChallenge
Dual pointer logicAdvancing i and j correctly with different rules (digit vs letter)
Number parsingInterpreting multiple digits from abbreviation and handling edge cases
ValidationMatching letters or rejecting early on invalid abbreviation structure
Constraint handlingRejecting abbreviations with leading zeros or invalid skips
Final checkMaking sure both i and j end together for a full match

๐Ÿ’ก Reflection Insight

This problem builds precision, pointer mastery, and string parsing fluency โ€” a combo that makes you dangerous in string-heavy DSA challenges (like wildcard matching, regex parsing, or expression evaluation). You're building a Jedi toolkit, shinobi ๐Ÿฅท๐Ÿ“œ๐Ÿ”ฅ