11package _16_18_Pattern_Matching ;
22
33// Algorithm:
4- // 0 ) If pattern is all the same letter (aaaaa... or bbbbb...), treat it as a special case.
5- // 1 ) Invert pattern (if necessary) to have it start with "a" instead of "b"
6- // 2 ) count numAs, numBs
7- // 3 ) try maxLengthA = 1 up to max it could validly be
4+ // 1 ) If pattern is all the same letter (aaaaa... or bbbbb...), treat it as a special case.
5+ // 2 ) Invert pattern (if necessary) to have it start with "a" instead of "b"
6+ // 3 ) count numAs, numBs
7+ // 4 ) try maxLengthA = 1 up to max it could validly be
88// - for each maxLengthA, calculate maxLengthB
99// - use a helper function: checkMatch(String value, String pattern, int aLength, int bLength)
1010
1111public class PatternMatching {
1212
13- public static boolean matches (String value , String pattern ) {
14- /* Special case: all same character in pattern */
15- if (pattern .indexOf ('a' ) == -1 || pattern .indexOf ('b' ) == -1 ) {
16- return value .length () % pattern .length () == 0 ; // wrong. must check if pattern properly repeats in value.
13+ public static boolean matches (String str , String pattern ) {
14+ if (str == null || pattern == null || pattern .length () > str .length ()) {
15+ return false ;
16+ } else if (pattern .length () == 0 ) {
17+ return str .length () == 0 ;
18+ } else if (pattern .indexOf ('a' ) == -1 || pattern .indexOf ('b' ) == -1 ) {
19+ return checkMatchRepeatingWord (str , pattern );
1720 }
1821
19- pattern = invert (pattern );
22+ pattern = invertIfNecessary (pattern );
2023 int numAs = countOf (pattern , 'a' );
2124 int numBs = pattern .length () - numAs ;
22- int maxLengthA = value .length () / numAs ;
25+ int maxLengthA = str .length () / numAs ;
2326 for (int lengthA = 1 ; lengthA <= maxLengthA ; lengthA ++) {
24- int charsForB = value .length () - lengthA * numAs ;
27+ int charsForB = str .length () - lengthA * numAs ;
2528 if (charsForB % numBs != 0 ) {
2629 continue ;
2730 }
2831 int lengthB = charsForB / numBs ;
29- if (checkMatch (value , pattern , lengthA , lengthB )) {
32+ if (checkMatch (str , pattern , lengthA , lengthB )) {
3033 return true ;
3134 }
3235 }
3336 return false ;
3437 }
3538
36- /* Changes pattern (if necessary) to start with 'a' instead of 'b'. Example: bbaba becomes aabab */
37- private static String invert (String pattern ) {
39+ // Changes pattern (if necessary) to start with 'a' instead of 'b'. Example: bbaba becomes aabab
40+ private static String invertIfNecessary (String pattern ) {
3841 if (pattern .charAt (0 ) == 'a' ) {
3942 return pattern ;
4043 }
@@ -59,22 +62,33 @@ private static int countOf(String str, char ch) {
5962 return count ;
6063 }
6164
62- private static boolean checkMatch (String value , String pattern , int aLength , int bLength ) {
63- /* Grab the 2 words matching "a" and "b" */
65+ private static boolean checkMatchRepeatingWord (String str , String pattern ) {
66+ int wordLength = str .length () / pattern .length ();
67+ String word = str .substring (0 , wordLength );
68+ for (int i = 0 ; i < str .length (); i += word .length ()) {
69+ if (!str .substring (i , i + word .length ()).equals (word )) {
70+ return false ;
71+ }
72+ }
73+ return true ;
74+ }
75+
76+ private static boolean checkMatch (String str , String pattern , int aLength , int bLength ) {
77+ // Grab the 2 words matching "a" and "b"
6478 int firstBinPattern = pattern .indexOf ('b' );
65- int firstBinValue = firstBinPattern * aLength ;
66- String aWord = value .substring (0 , aLength );
67- String bWord = value .substring (firstBinValue , firstBinValue + bLength );
79+ int firstBinValue = firstBinPattern * aLength ;
80+ String aWord = str .substring (0 , aLength );
81+ String bWord = str .substring (firstBinValue , firstBinValue + bLength );
6882
6983 int i = 0 ;
7084 for (int j = 0 ; j < pattern .length (); j ++) {
7185 if (pattern .charAt (j ) == 'a' ) {
72- if (!value .substring (i , i + aLength ).equals (aWord )) {
86+ if (!str .substring (i , i + aLength ).equals (aWord )) {
7387 return false ;
7488 }
7589 i += aLength ;
7690 } else if (pattern .charAt (j ) == 'b' ) {
77- if (!value .substring (i , i + bLength ).equals (bWord )) {
91+ if (!str .substring (i , i + bLength ).equals (bWord )) {
7892 return false ;
7993 }
8094 i += bLength ;
@@ -85,3 +99,4 @@ private static boolean checkMatch(String value, String pattern, int aLength, int
8599}
86100
87101// Time Complexity: O(n^2)
102+ // Space Complexity: O(n)
0 commit comments