leetcode (30) Substring with Concatenation of All Words

原题链接:https://leetcode.com/problems/substring-with-concatenation-of-all-words/


题目:30. Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexactly once and without any intervening characters.

For example, given:
s"barfoothefoobarman"
words["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).


题目意思:就是在s中找到所有的序号,从这些序号开始的所有的单词,全都包含了words中的单词,并且中间不能含有其它的单词。


解题思路:

(1)首先应该建一个hashmap,以words的单词作为map的key,以words中出现的数量作为value值。

(2)在s中进行遍历,因为每个words中的单词长度都是固定的length,所以依次比较(i,i+length-1),(i+length,i+2*length-1),(i+2*length, i+3*length-1)。。。看是否能和words中的单词都能进行匹配。

(3)若可以匹配,则保存i,继续判断s中的i+1作为起始位置。。。依次类推


代码实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SIZE 1000

typedef struct Node{
    char *word;
    int times;
    struct Node *next;
}data;

int hash(char *word){
    int i = 0, h = 0;
    for(i=0; word[i]; i++) {
        h = (h*31+word[i])%SIZE;
    }
    return h;
}
//根据words构建字典
int insertMap(data **map, char *word, int length) {
    int h = hash(word);
    if (map[h] == NULL) {
        map[h] = (data *) malloc (sizeof(data));
        map[h]->word = (char *) malloc (sizeof(char) * (length+1));
        strcpy(map[h]->word, word);
        map[h]->times = 1;
        map[h]->next = NULL;
        return 1;
    } else {
        data *p = map[h];
        while (p->next != NULL) {
            if (strcmp(p->word, word) == 0) {
                p->times++;
                return p->times;
            }
            p = p->next;
        }
        if (strcmp(p->word, word) == 0) {
            p->times++;
            return p->times;
        } else {
            data *tmp = (data *) malloc (sizeof(data));
            tmp->word = (char *) malloc (sizeof(char) * (length+1));
            strcpy(tmp->word, word);
            tmp->times = 1;
            p->next = tmp;
            tmp->next = NULL;
            return 1;
        }
    }
}
//查询字典,并返回此单词的数目
int findMap(data **map, char *sub) {
    int h = hash(sub);
    if (map[h] == NULL) {
        return -1;
    } else {
        data *p = map[h];
        while (p != NULL) {
            if (strcmp(p->word, sub) == 0) {
                return p->times;
            }
            p = p->next;
        }
        return -1;
    }
}

char *substring(char *s, int start, int len) {
    char *sub = (char *) malloc (sizeof(char) * (len+1));
    int i=0;
    for (; i < len; i++) {
        sub[i] = s[i+start];
    }
    sub[i] = '\0';
    return sub;
}
/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* findSubstring(char* s, char** words, int wordsSize, int* returnSize) {
    *returnSize = 0;
    if (s == NULL || words == NULL) {
        return NULL;
    }
    int sLen = strlen(s), wLen = strlen(words[0]);
    int *result = (int *) malloc (sizeof(int) * (sLen-wLen*wordsSize+1));
    data **map = (data **) malloc (sizeof(data *) * SIZE);
    data **tmp = (data **) malloc (sizeof(data *) * SIZE);
    int i, j;
    for (i = 0; i < SIZE; i++) {
        map[i] = NULL;
        tmp[i] = NULL;
    }

    //构建字典
    for (i = 0; i < wordsSize; i++) {
        insertMap(map, words[i], wLen);
    }

    for (i = 0; i <= sLen-wLen*wordsSize; i++) {
        for (j = 0; j < SIZE; j++) {
            if (tmp[j] != NULL) {
                free(tmp[j]);
                tmp[j] = NULL;
            }
        }
        for (j = 0; j < wordsSize; j++) {
            char *sub = substring(s, i+j*wLen, wLen);
            int mapnum = findMap(map, sub);
            if (mapnum == -1) break;
            int num = insertMap(tmp, sub, wLen);
            if (num > mapnum) break;
            free(sub);
        }
        if (j >= wordsSize) {
            result[(*returnSize)++] = i;
        }
    }
    for (i = 0; i < SIZE; i++) {
        if (map[i] != NULL) {
            free(map[i]);
        }
    }
    free(map);
    return result;
}


以上代码参考了别人的一篇博客。


还有一种方法是滑动窗口的方法,思路仍然是维护一个窗口,如果当前单词在字典中,则继续移动窗口右端,否则窗口左端可以跳到字符串下一个单词了:http://blog.csdn.net/linhuanmars/article/details/20342851


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值