Detailed Explanation | Case wise solution
Observation 1: \n>We need to find a substring that contains:\n>\n>1. Even occurrences of 0, 1, 2, 3 ... 9.\n>OR\n>2. Odd occurrences of one of 0, 1, 2, 3 ... 9.
>Observation 1: \n>We need to find a substring that contains:\n>\n>1. Even occurrences of 0, 1, 2, 3 ... 9.\n>OR\n>2. Odd occurrences of one of 0, 1, 2, 3 ... 9. And even occurrences of all other digits.\n\nNow, let\'s enumerate occurrences of each digit for this string "011233444555569". And for even occurrences of a digit represent it as set bit in our state.\n\n"": will have following occurrences: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) => (1111111111)base2\n"0": will have following occurrences: (1, 0, 0, 0, 0, 0, 0, 0, 0, 0) => (1111111110)base2\n"01": will have following occurrences: (1, 1, 0, 0, 0, 0, 0, 0, 0, 0) => (1111111100)base2\n"011": will have following occurrences: (1, 2, 0, 0, 0, 0, 0, 0, 0, 0) => (1111111110)base2\n"0112": will have following occurrences: (1, 2, 1, 0, 0, 0, 0, 0, 0, 0) => (1111111010)base2\n\nMaintaining state in the form of bits will help us find index which will give us a substring that satisfy case1 or case2. Let\'s see how:\n\nFor observation 1 case 1: For this case we only need to check when did we encountered the same set bits earlier.\n\nBecause to get even occurences of a digit that has even occurrences we must\'ve had even occurrences earlier. And to get even occurrences of a digit that has odd occurrences we must\'ve had odd occurrences of same digit earlier. \n\nWhy?\n\n>Observation 2: \n>even - even = even\n>odd - odd = even\n\nFor observation 1 case 2: Keep even occurrences of each digit and use odd occurrence of one of the digit and see if there is a longer substring.\n\n**Case wise, light bit-wise operation, easy to understand solution:**\n\n```\nclass Solution {\n    public int longestAwesome(String s) {\n        Map<Integer, Integer> pos = new HashMap<>();   // `state` => index of first occurence of this `state`\n        int[] occurrences = new int[10];\n\n        // Minimum answer will always be 1\n        int ans = 1;\n\n        // All digits have even number of occurences in the beginning.\n        pos.put(1023, -1);\n\n        for (int i = 0; i < s.length(); ++i) {\n            occurrences[s.charAt(i) - \'0\']++;\n\n            int currentState = 0;\n            for (int j = 0; j < 10; ++j) {\n                if (occurrences[j] % 2 == 0) {\n                    currentState |= (1 << j);\n                }\n            }\n            // Case 1: All even\n            ans = Math.max(ans, i - pos.getOrDefault(currentState, i));\n\n            // Case 2: All even, except one odd\n            for (int digitWithOddOccurrences = 0; digitWithOddOccurrences < 10; ++digitWithOddOccurrences) {\n                int state = 0;\n                for (int j = 0; j < 10; ++j) {\n                    if (j != digitWithOddOccurrences) {\n                        if (occurrences[j] % 2 == 0) {\n                            state |= (1 << j);\n                        }\n                    } else {\n                        if (occurrences[j] % 2 == 1) {\n                            state |= (1 << j);\n                        }\n                    }\n                }\n\n                ans = Math.max(ans, i - pos.getOrDefault(state, i));\n            }\n            if (!pos.containsKey(currentState)) {\n                pos.put(currentState, i);\n            }\n        }\n\n        return ans;\n    }\n}\n```\n\n**Refactored solution:**\n\n```\nclass Solution {\n    public int longestAwesome(String s) {\n        Map<Integer, Integer> pos = new HashMap<>();   // `state` => index of first occurence of this `state`\n        int[] occurrences = new int[10];\n\n        // Minimum answer will always be 1\n        int ans = 1;\n        \n        // All digits have even number of occurences in the beginning.\n        int currentState = 1023;\n\n        pos.put(currentState, -1);\n\n        for (int i = 0; i < s.length(); ++i) {\n            currentState ^= (1 << (s.charAt(i) - \'0\'));\n            \n            // Case 1: All even\n            ans = Math.max(ans, i - pos.getOrDefault(currentState, i));\n\n            // Case 2: All even, except one odd\n            for (int digitWithOddOccurrences = 0; digitWithOddOccurrences < 10; ++digitWithOddOccurrences) {\n                ans = Math.max(ans, i - pos.getOrDefault(currentState ^ (1 << digitWithOddOccurrences), i));\n            }\n            if (!pos.containsKey(currentState)) {\n                pos.put(currentState, i);\n            }\n        }\n\n        return ans;\n    }\n}\n```
[]