#include #include #include #include const uint32_t N = 100000000; const uint32_t M = 12, Z = 26, ZA = 32, H = M + 1; static const char* mnames[M + 1] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; static const uint32_t mhash[H] = {0, 2, 6, 1, 10, 4, 7, 11, 3, 8, 9, 12, 5}; uint32_t month_to_num(const unsigned char *s) { uint32_t c0 = s[0] - 'A'; if (Z <= c0) return 0; uint32_t c1 = s[1] - 'a'; if (Z <= c1) return 0; uint32_t c2 = s[2] - 'a'; if (Z <= c2) return 0; if (s[3]) return 0; uint32_t z = ((1431655833 * c2) ^ c1) % H; if (z == 0) return z; z = mhash[z]; assert (0 < z && z <= M); const unsigned char *s0 = (const unsigned char *) mnames[z]; if (s[0] != s0[0] || s[1] != s0[1] || s[2] != s0[2]) return 0; return z; } static uint32_t mbs[M + 1][2] = { {0, 0}, {0x417072, 4}, {0x417567, 8}, {0x446563, 12}, {0x466562, 2}, {0x4a616e, 1}, {0x4a756c, 7}, {0x4a756e, 6}, {0x4d6172, 3}, {0x4d6179, 5}, {0x4e6f76, 11}, {0x4f6374, 10}, {0x536570, 9} }; uint32_t month_to_num_bs(const unsigned char *s) { uint32_t c0 = s[0]; if (!c0) return 0; uint32_t c1 = s[1]; if (!c1) return 0; uint32_t c2 = s[2]; if (!c2) return 0; if (s[3]) return 0; uint32_t z = c0 * 65536 + c1 * 256 + c2; uint32_t k; #if 1 #if 0 if (z <= mbs[6][0]) { k = (z <= mbs[3][0]) ? 3 : 6; } else { k = (z <= mbs[9][0]) ? 9 : M; } #else k = (z <= mbs[6][0]) ? 6 : M; #endif #else k = M; #endif for (; z < mbs[k][0]; k--) ; return mbs[k][0] == z ? mbs[k][1] : 0; } static uint8_t tree[20][ZA]; void prepare_tree() { memset(tree, 0, sizeof(tree)); uint32_t tree_size = 2; for (uint32_t i = 1; i <= M; i++) { uint8_t p = 1; uint32_t c = mnames[i][0] - 'A'; assert (c < Z); if (tree[p][c] == 0) { tree[p][c] = tree_size++; } p = tree[p][c]; c = mnames[i][1] - 'a'; assert (c < Z); if (tree[p][c] == 0) { tree[p][c] = tree_size++; } p = tree[p][c]; c = mnames[i][2] - 'a'; assert (c < Z); assert (tree[p][c] == 0); tree[p][c] = i; } // printf("tree_size = %u \n", tree_size); } uint32_t month_to_num_tree(const unsigned char *s) { uint32_t c0 = s[0] - 'A'; if (Z <= c0) return 0; uint32_t p = tree[1][c0]; uint32_t c1 = s[1] - 'a'; if (Z <= c1) return 0; p = tree[p][c1]; uint32_t c2 = s[2] - 'a'; if (Z <= c2) return 0; p = tree[p][c2]; if (s[3]) return 0; return p; } int main() { prepare_tree(); #if 1 uint32_t acc = 0; for (uint32_t j = 0; j < N; j++) { for (uint32_t i = 0; i <= M; i++) { acc += month_to_num_tree((const unsigned char*) mnames[i]); } } printf("acc = %u \n", acc); #endif for (uint32_t i = 0; i <= M; i++) { uint32_t z = month_to_num_tree((const unsigned char*) mnames[i]); printf("%3s %2u %2u \n", mnames[i], z, i); } return 0; }