diff --git a/140_word_break_ii/Makefile b/140_word_break_ii/Makefile new file mode 100644 index 0000000..a9604bc --- /dev/null +++ b/140_word_break_ii/Makefile @@ -0,0 +1,2 @@ +all: + gcc -O2 -o test word_break.c diff --git a/140_word_break_ii/word_break.c b/140_word_break_ii/word_break.c new file mode 100644 index 0000000..97e4bac --- /dev/null +++ b/140_word_break_ii/word_break.c @@ -0,0 +1,208 @@ +#include +#include +#include + +struct list_head { + struct list_head *next, *prev; +}; + +static inline void +INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list->prev = list; +} + +static inline int +list_empty(const struct list_head *head) +{ + return (head->next == head); +} + +static inline void +__list_add(struct list_head *new, struct list_head *prev, struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +static inline void +list_add(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head, head->next); +} + +static inline void +list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +static inline void +__list_del(struct list_head *entry) +{ + entry->next->prev = entry->prev; + entry->prev->next = entry->next; +} + +static inline void +list_del(struct list_head *entry) +{ + __list_del(entry); + entry->next = entry->prev = NULL; +} + +#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 list_for_each(p, head) \ + for (p = (head)->next; p != (head); p = p->next) + +#define list_for_each_safe(p, n, head) \ + for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) + +struct word_node { + char *word; + struct list_head link; +}; + +struct recur_cache { + int num; + int cap; + struct list_head **heads; +}; + +static struct recur_cache *resize(struct recur_cache **caches, int index) +{ + int i; + struct recur_cache *cache = caches[index]; + if (cache->num + 1 > cache->cap) { + cache->cap *= 2; + struct list_head **heads = malloc(cache->cap * sizeof(*heads)); + for (i = 0; i < cache->cap; i++) { + if (i < cache->num) { + heads[i] = cache->heads[i]; + } else { + heads[i] = malloc(sizeof(struct list_head)); + INIT_LIST_HEAD(heads[i]); + } + } + free(cache->heads); + cache->heads = heads; + } + + return cache; +} + +static struct recur_cache *recursive(char *s, char **words, int *sizes, int num, + struct recur_cache **caches, int len, int index) +{ + int i, j; + struct word_node *wn; + struct recur_cache *result; + + if (*s == '\0') { + return NULL; + } else if (caches[index] != NULL) { + return caches[index]; + } else { + result = malloc(sizeof(*result)); + result->num = 0; + result->cap = 1; + result->heads = malloc(sizeof(struct list_head *)); + result->heads[0] = malloc(sizeof(struct list_head)); + INIT_LIST_HEAD(result->heads[0]); + caches[index] = result; + for (i = 0; i < num; i++) { + if (!memcmp(s, words[i], sizes[i])) { + struct recur_cache *next = recursive(s + sizes[i], words, sizes, num, caches, len, index + sizes[i]); + if (next != NULL) { + int k = result->num; + for (j = k; j < k + next->num; j++) { + result = resize(caches, index); + wn = malloc(sizeof(*wn)); + wn->word = words[i]; + list_add(&wn->link, result->heads[j]); + + struct list_head *p; + list_for_each(p, next->heads[j - k]) { + struct word_node *wnn = list_entry(p, struct word_node, link); + wn = malloc(sizeof(*wn)); + wn->word = wnn->word; + list_add_tail(&wn->link, result->heads[j]); + } + result->num++; + } + } else { + wn = malloc(sizeof(*wn)); + wn->word = words[i]; + list_add(&wn->link, result->heads[result->num++]); + } + } + } + + return result; + } +} + +/** + ** Return an array of size *returnSize. + ** Note: The returned array must be malloced, assume caller calls free(). + **/ +static char **wordBreak(char* s, char** wordDict, int wordDictSize, int *returnSize) +{ + if (wordDictSize == 0) { + *returnSize = 0; + return NULL; + } + + int i, total = 0; + int len = strlen(s); + int *sizes = malloc(wordDictSize * sizeof(int)); + + /* Add into hash list */ + for (i = 0; i < wordDictSize; i++) { + sizes[i] = strlen(wordDict[i]); + total += sizes[i]; + } + + struct recur_cache **caches = malloc(len * sizeof(*caches)); + memset(caches, 0, len * sizeof(*caches)); + struct recur_cache *cache = recursive(s, wordDict, sizes, wordDictSize, caches, len, 0); + + char **results = malloc(cache->num * sizeof(char *)); + for (i = 0; i < cache->num; i++) { + results[i] = malloc(total + 100); + char *p = results[i]; + struct list_head *n; + list_for_each(n, cache->heads[i]) { + struct word_node *wn = list_entry(n, struct word_node, link); + char *q = wn->word; + while ((*p++ = *q++) != '\0') {} + *(p - 1) = ' '; + } + *(p - 1) = '\0'; + } + + *returnSize = cache->num; + return results; +} + +int main(int argc, char **argv) +{ + if (argc < 3) { + fprintf(stderr, "Usage: ./test word dictionary...\n"); + exit(-1); + } + + int i, count = 0; + char **list = wordBreak(argv[1], argv + 2, argc - 2, &count); + for (i = 0; i < count; i++) { + printf("%s\n", list[i]); + } + return 0; +} diff --git a/146_lru_cache/lru_cache.c b/146_lru_cache/lru_cache.c index 6a2536d..a11558f 100644 --- a/146_lru_cache/lru_cache.c +++ b/146_lru_cache/lru_cache.c @@ -60,10 +60,10 @@ static inline void hlist_del(struct hlist_node *n) #define list_last_entry(ptr, type, field) list_entry((ptr)->prev, type, field) #define list_for_each(p, head) \ - for (p = (head)->next; p != (head); p = p->next) + for (p = (head)->next; p != (head); p = p->next) #define list_for_each_safe(p, n, head) \ - for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) + for (p = (head)->next, n = p->next; p != (head); p = n, n = p->next) struct list_head { struct list_head *next, *prev; @@ -81,18 +81,6 @@ list_empty(const struct list_head *head) return (head->next == head); } -static inline int -list_is_first(const struct list_head *list, const struct list_head *head) -{ - return list->prev == head; -} - -static inline int -list_is_last(const struct list_head *list, const struct list_head *head) -{ - return list->next == head; -} - static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { @@ -124,15 +112,15 @@ __list_del(struct list_head *entry) static inline void list_del(struct list_head *entry) { - __list_del(entry); - entry->next = entry->prev = NULL; + __list_del(entry); + entry->next = entry->prev = NULL; } static inline void list_move(struct list_head *list, struct list_head *head) { - __list_del(list); - list_add(list, head); + __list_del(list); + list_add(list, head); } static inline void