A Finite State Machine (FSM) can be designed to recognise strings that end with a specific suffix. In this post, we build a 4-state FSM that accepts strings over the alphabet {a, b} which end with the suffix ‘abb’. Unlike the “contains” variant, here only the final state of the machine matters — the string is accepted if and only if the last three characters form ‘abb’. The FSM also prints a state trace showing each transition as it processes the input.
FSM to Check if String Ends with ‘abb’ in Java
import java.io.*;
class FsmEndsWithAbb {
public static void main(String[] args) throws IOException {
/**
* Transition table: transitionTable[currentState][inputSymbol] = nextState
* Column 0 = input 'a', Column 1 = input 'b'
*
* State meanings:
* State 0 -- initial/reset state (no useful suffix progress)
* State 1 -- last character seen was 'a'
* State 2 -- last two characters seen were 'ab'
* State 3 -- last three characters were 'abb' (accept state)
*/
int[][] transitionTable = {
{1, 0}, // State 0: 'a' go to State 1, 'b' stay at State 0
{1, 2}, // State 1: 'a' stay at State 1, 'b' go to State 2
{1, 3}, // State 2: 'a' go to State 1, 'b' go to State 3
{0, 1} // State 3: 'a' reset to State 0, 'b' go to State 1
};
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter String:");
String inputString = reader.readLine();
int currentState = 0;
System.out.print("q" + currentState); // Print starting state
// Process each character, follow transitions, and print state trace
for (int i = 0; i < inputString.length(); i++) {
char currentChar = inputString.charAt(i);
if (currentChar == 'a') {
currentState = transitionTable[currentState][0];
System.out.print("->q" + currentState);
} else if (currentChar == 'b') {
currentState = transitionTable[currentState][1];
System.out.print("->q" + currentState);
}
}
System.out.println();
// Accepted only if we finish in State 3 (string ends with 'abb')
if (currentState == 3) {
System.out.println("String ends with 'abb' -- Accepted");
} else {
System.out.println("String does not end with 'abb' -- Rejected");
}
}
}
How the Code Works
- Transition table: The 4×2 array encodes the FSM. Each row is a state; column 0 handles ‘a’ and column 1 handles ‘b’. The table is designed so that being in State 3 means exactly that the last three characters processed were ‘a’, ‘b’, ‘b’.
- State 3 is not a trap: Unlike the “contains” FSM, State 3 here transitions elsewhere when more characters follow. If ‘a’ comes after ‘abb’, the machine moves to State 0, correctly reflecting that a string continuing beyond ‘abb’ may not end with it.
- State trace: Each transition prints an arrow and the new state label, giving a visible trace of the machine’s path through execution.
- Decision: After consuming the entire string, if
currentState == 3, the string ends with ‘abb’; otherwise it does not.
Sample Output
Enter String:
abbaaaabb
q0->q1->q2->q3->q0->q1->q1->q1->q2->q3
String ends with 'abb' -- Accepted
Enter String:
babababa
q0->q0->q1->q2->q1->q2->q1->q2->q1
String does not end with 'abb' -- Rejected
Output Explanation
- For
abbaaaabb: The FSM traces q0→q1 (a) →q2 (b) →q3 (b) →q0 (a) →q1 (a) →q1 (a) →q1 (a) →q2 (b) →q3 (b). The final state is 3 → Accepted. The string ends with ‘abb’. - For
babababa: The FSM alternates between states as ‘b’ and ‘a’ are processed. The string ends at the final ‘a’, landing in State 1 (not State 3) → Rejected. The string ends with ‘a’, not ‘abb’. - Note that
abbaaaabbalso contains ‘abb’ multiple times, but this FSM only cares about the suffix — it checks the final state, not intermediate ones.
See Also
- Finite State Machine: Check Whether String Contains ‘abb’ or not
- Finite State Machine: Check Whether Number is Divisible by 3 or not
- Finite State Machine: Implementing Binary Adder in Java
- Push Down Automata: Equal Number of a’s and b’s in Java
- Illustrating Epsilon Closure in Java
Conclusion
This FSM illustrates an important distinction: checking a suffix condition versus a containment condition. State 3 is a non-trapping accepting state here — the machine can leave it if the pattern is broken by further input. This property makes the transition table slightly more complex but is key to correctly recognising suffix patterns. The state-trace output is also a useful debugging tool when reasoning about FSM behaviour.