Skip to content

Commit

Permalink
Remove uthash
Browse files Browse the repository at this point in the history
Signed-off-by: begeekmyfriend <[email protected]>
  • Loading branch information
begeekmyfriend committed Oct 17, 2017
1 parent 88cf82c commit 634d295
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 1,189 deletions.
94 changes: 55 additions & 39 deletions 030_substring_with_concatenation_of_all_words/concatenation.c
Original file line number Diff line number Diff line change
@@ -1,84 +1,100 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "../uthash.h"

struct word_hash {
char *word;
int freq;
int index;
UT_hash_handle hh;
};

static struct word_hash *hash_table = NULL;
static inline int BKDRHash(char *s, size_t size)
{
int seed = 31; /* 131 1313 13131... */
unsigned long hash = 0;
while (*s != '\0') {
hash = hash * seed + *s++;
}
return hash % size;
}

static int find(char *word, struct word_hash *table, int size)
{
int i, first = 1, hash = BKDRHash(word, size);
for (i = hash; first || i != hash; i = ++i % size) {
first = 0;
if (table[i].freq > 0 && !strcmp(table[i].word, word)) {
return i;
}
}
return -1;
}

/**
** Return an array of size *returnSize.
** Note: The returned array must be malloced, assume caller calls free().
**/
static int* findSubstring(char* s, char** words, int wordsSize, int* returnSize) {
if (s == NULL || wordsSize == 0) {
static int *findSubstring(char *s, char **words, int wordsSize, int *returnSize)
{
if (*s == '\0' || wordsSize == 0) {
*returnSize = 0;
return NULL;
}

int i, index, cap = 1, count = 0;
int i, j, cap = 500, count = 0;
char *start = s;
struct word_hash *obj, *tmp;
struct word_node *wn;
int hash_size = wordsSize;
int len = strlen(words[0]);
char *word = malloc(len + 1);
int length = strlen(s) - wordsSize * len + 1;
int *indexes = malloc(cap * sizeof(int));
int *freqs = malloc(wordsSize * sizeof(int));
int *sub_indexes = malloc(cap * sizeof(int));
struct word_hash *table = malloc(hash_size * sizeof(*table));

word[len] = '\0';
memset(table, 0, hash_size * sizeof(*table));
for (i = 0; i < wordsSize; i++) {
HASH_FIND_STR(hash_table, words[i], obj);
if (obj == NULL) {
obj = malloc(sizeof(*obj));
obj->word = words[i];
obj->freq = 1;
obj->index = i;
HASH_ADD_STR(hash_table, word, obj);
} else {
obj->freq++;
int hash = BKDRHash(words[i], hash_size);
for (j = hash; table[j].freq > 0 && strcmp(table[j].word, words[i]); j = ++j % hash_size) {}
if (table[j].freq == 0) {
table[j].word = words[i];
}
table[j].freq++;
}

while (length-- > 0) {
int sum = 0;
memset(freqs, 0, wordsSize * sizeof(int));
word[len] = '\0';
int length = len * wordsSize - 1;
while (s[length] != '\0') {
memset(freqs, 0, hash_size * sizeof(int));
for (i = 0; i < wordsSize; i++) {
memcpy(word, s + i * len, len);
HASH_FIND_STR(hash_table, word, obj);
if (obj == NULL) {
int index = find(word, table, hash_size);
if (index < 0) {
break;
} else {
sum += ++freqs[obj->index] <= obj->freq ? 1 : -1;
if (++freqs[index] > table[index].freq) {
break;
}
}
}
if (sum == wordsSize && i == wordsSize) {
if (count + 1 >= cap) {
cap *= 2;
sub_indexes = realloc(sub_indexes, cap * sizeof(int));
}
sub_indexes[count++] = s - start;

if (i == wordsSize) {
indexes[count++] = s - start;
}
s++;
}

HASH_ITER(hh, hash_table, obj, tmp) {
HASH_DEL(hash_table, obj);
free(obj);
}

*returnSize = count;
return sub_indexes;
return indexes;
}

int main(int argc, char **argv)
{
int i, count;
if (argc < 3) {
fprintf(stderr, "Usage: ./test str w1 w2...\n");
exit(-1);
}

int i, count = 0;
int *indexes = findSubstring(argv[1], argv + 2, argc - 2, &count);
for (i = 0; i < count; i++) {
printf("%d ", indexes[i]);
Expand Down
136 changes: 93 additions & 43 deletions 049_group_anagrams/anagrams.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,58 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../uthash.h"

struct str_hash {
char *str;
int *indexes;
int freq;
int cap;
UT_hash_handle hh;

struct hlist_node;

struct hlist_head {
struct hlist_node *first;
};

struct hlist_node {
struct hlist_node *next, **pprev;
};

static inline void INIT_HLIST_HEAD(struct hlist_head *h) {
h->first = NULL;
}

static inline int hlist_empty(struct hlist_head *h) {
return !h->first;
}

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
if (h->first != NULL) {
h->first->pprev = &n->next;
}
n->next = h->first;
n->pprev = &h->first;
h->first = n;
}

#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - (size_t)&(((type *)0)->member)))

#define list_entry(ptr, type, member) \
container_of(ptr, type, member)

#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos; pos = pos->next)

struct word_node {
struct hlist_node node;
int index;
};

static struct str_hash *hash_table = NULL;
struct word_hash {
struct hlist_head head;
char *word;
int num;
};

static void insert_sort(char *s, int len)
{
long i, j;
int i, j;
for (i = 1; i < len; i++) {
char tmp = s[i];
j = i - 1;
Expand All @@ -26,68 +63,81 @@ static void insert_sort(char *s, int len)
}
}

static inline int BKDRHash(char *s, size_t size)
{
int seed = 31; /* 131 1313 13131... */
unsigned long hash = 0;
while (*s != '\0') {
hash = hash * seed + *s++;
}
return hash % size;
}

/**
** Return an array of arrays of size *returnSize.
** The sizes of the arrays are returned as *columnSizes array.
** Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
**/
static char*** groupAnagrams(char** strs, int strsSize, int** columnSizes, int* returnSize) {
int i, j, count = 0;
struct str_hash *obj, *tmp;
char **words = malloc(strsSize * sizeof(char *));
struct word_node *wn;

int hash_size = strsSize;
struct word_hash *ht = malloc(hash_size * sizeof(*ht));
for (i = 0; i < hash_size; i++) {
INIT_HLIST_HEAD(&ht[i].head);
ht[i].num = 0;
}

char **words = malloc(strsSize * sizeof(char *));
for (i = 0; i < strsSize; i++) {
int len = strlen(strs[i]);
words[i] = malloc(len + 1);
strcpy(words[i], strs[i]);
insert_sort(words[i], len);
HASH_FIND_STR(hash_table, words[i], obj);
if (obj == NULL) {
obj = malloc(sizeof(*obj));
obj->str = words[i];
obj->freq = 1;
obj->cap = 1;
obj->indexes = malloc(sizeof(int));
obj->indexes[0] = i;
HASH_ADD_STR(hash_table, str, obj);
int hash = BKDRHash(words[i], hash_size);
/* find available hash bucket */
for (j = hash; ht[j].num > 0 && strcmp(ht[j].word, words[i]); j = ++j % hash_size) {}
wn = malloc(sizeof(*wn));
wn->index = i;
if (ht[j].num == 0) {
ht[j].word = words[i];
count++;
} else {
if (obj->freq + 1 >= obj->cap) {
obj->cap *= 2;
obj->indexes = realloc(obj->indexes, obj->cap * sizeof(int));
}
obj->indexes[obj->freq++] = i;
}
hlist_add_head(&wn->node, &ht[j].head);
ht[j].num++;
}

char ***ret_lists = malloc(count * sizeof(char **));
int *column_sizes = malloc(count * sizeof(int));

i = 0;
HASH_ITER(hh, hash_table, obj, tmp) {
ret_lists[i] = malloc(obj->freq * sizeof(char *));
column_sizes[i] = obj->freq;
for (j = 0; j < column_sizes[i]; j++) {
ret_lists[i][j] = strs[obj->indexes[j]];
j = 0;
struct hlist_node *p;
char ***lists = malloc(count * sizeof(char **));
*columnSizes = malloc(count * sizeof(int));
for (i = 0; i < hash_size; i++) {
if (ht[i].num > 0) {
(*columnSizes)[j] = ht[i].num;
lists[j] = malloc(ht[i].num * sizeof(char *));
int k = 0;
hlist_for_each(p, &ht[i].head) {
wn = list_entry(p, struct word_node, node);
lists[j][k++] = strs[wn->index];
}
j++;
}
HASH_DEL(hash_table, obj);
free(obj);
i++;
}

*columnSizes = column_sizes;
*returnSize = count;
return ret_lists;
return lists;
}

int main(int argc, char **argv)
{
int *column_sizes, count, i, j;
int *column_sizes, count = 0, i, j;
char ***lists = groupAnagrams(argv + 1, argc - 1, &column_sizes, &count);
for (i = 0; i < count; i++) {
for (j = 0; j < column_sizes[i]; j++) {
printf("%s\n", lists[i][j]);
printf("%s ", lists[i][j]);
}
printf("\n");
}
return 0;
}
Loading

0 comments on commit 634d295

Please sign in to comment.