Often you need only a piece of a string: the prefix of a product code, the name in front of an email address, the file extension at the end. substring() cuts that piece out.
Give one index and you get everything from that position to the end. Positions count from zero:
String code = 'LC-1234'; System.debug(code.substring(3)); // 1234
Two indexes give you the characters from the first index up to but NOT including the second:
System.debug(code.substring(0, 2)); // LC
These are shortcuts when you count from either end:
System.debug(code.left(2)); // LC System.debug(code.right(4)); // 1234
Combine indexOf() or lastIndexOf() with substring() to cut at a marker instead of a fixed position:
String email = 'ada@example.com';
Integer at = email.indexOf('@');
System.debug(email.substring(0, at)); // ada
System.debug(email.substring(at + 1)); // example.com
lastIndexOf() works the same way but searches from the end, which is what you want when the marker can appear more than once.
An index past the end of the string throws a StringException, so check length() when you are not sure. And remember that indexOf() returns -1 when the marker is missing, which is never a safe index to cut at.
Real data almost never arrives in exactly the shape you need. Slicing text apart at a known marker is the everyday tool for pulling the useful piece out of it.