Следующее регулярное выражение работает по желанию:
(?i)A|B(?!.*[A-A])|C(?!.*[A-B])|D(?!.*[A-C])|E(?!.*[A-D])|F(?!.*[A-E])|G(?!.*[A-F])|H(?!.*[A-G])|I(?!.*[A-H])|J(?!.*[A-I])|K(?!.*[A-J])|L(?!.*[A-K])|M(?!.*[A-L])|N(?!.*[A-M])|O(?!.*[A-N])|P(?!.*[A-O])|Q(?!.*[A-P])|R(?!.*[A-Q])|S(?!.*[A-R])|T(?!.*[A-S])|U(?!.*[A-T])|V(?!.*[A-U])|W(?!.*[A-V])|X(?!.*[A-W])|Y(?!.*[A-X])|Z(?!.*[A-Y])
Регулярное выражение состоит из 26 терминов (один термин на букву), которые объединяются через оператор чередования (|). A (?! B) - это оператор отрицательного просмотра, который соответствует A, если за A не следует B. За (? I) просто запускается нечувствительность к регистру.
В целом регулярное выражение находит сначала все буквы А слева направо, затем все буквы слева направо и т. Д.
Из-за длины регулярного выражения его удобнее создавать программно:
// Generate regEx
String regEx = "(?i)" + "A" + "|";
for (char i = 'B'; i <= 'Z'; i++ ) {
regEx += i + "(?!.*[A-" + (char)(i-1) + "])" + "|";
}
regEx = regEx.substring(0, regEx.length() - 1);
System.out.println(regEx);
Для следующего примера:
String example = "AAAZZZHHAAAZZHHHAAZZZHH";
// Output
while(example.length() != 0) {
System.out.println(example);
example = example.replaceFirst(regEx, "");
}
вывод:
AAAZZZHHAAAZZHHHAAZZZHH
AAZZZHHAAAZZHHHAAZZZHH
AZZZHHAAAZZHHHAAZZZHH
ZZZHHAAAZZHHHAAZZZHH
ZZZHHAAZZHHHAAZZZHH
ZZZHHAZZHHHAAZZZHH
ZZZHHZZHHHAAZZZHH
ZZZHHZZHHHAZZZHH
ZZZHHZZHHHZZZHH
ZZZHZZHHHZZZHH
ZZZZZHHHZZZHH
ZZZZZHHZZZHH
ZZZZZHZZZHH
ZZZZZZZZHH
ZZZZZZZZH
ZZZZZZZZ
ZZZZZZZ
ZZZZZZ
ZZZZZ
ZZZZ
ZZZ
ZZ
Z