当前位置: 代码网 > it编程>编程语言>Java > 30. 串联所有单词的子串

30. 串联所有单词的子串

2024年08月01日 Java 我要评论
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。“acdbef” 不是串联子串,因为他不是任何 words 排列的连接。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]

30. 串联所有单词的子串

在这里插入图片描述


c代码:滑动窗口、字符串异位段

// 此题是 字母异位词 的进阶题;字符串异位段
// 1、创建words的哈希表,记录word、次数、下标idx(对比438,相当于是判断哈希数组相等!)
// 2、类比判断哈希数组相等的条件:遍历每一个str,str出现在words中,次数相等,窗口的长度与words所有串的长度相等!
// 3、str不出现在words中,l右移一个step,清空hash,重新开始;
// 4、hash[idx] > cnt 滑动窗口左移;

typedef struct {
    char *str;
    int cnt;
    int idx;
    ut_hash_handle hh;
} hashtable;

hashtable* addhash(char **words, int wordssize) {
    hashtable* head = null;
    hashtable* out = null;
    for (int r = 0; r < wordssize; r++) {
        hash_find_str(head, words[r], out);
        if(null == out) {
            out = (hashtable*)malloc(sizeof(hashtable));
            out->str = words[r];
            out->cnt = 1;
            out->idx = r;
            hash_add_str(head, str, out);
        } else {
            out->cnt++;
        }
    }
    return head;
}

int* findsubstring(char * s, char** words, int wordssize, int* returnsize){
    int step  = strlen(words[0]);  // words的字符串长度相等
    int lenhash = step * wordssize;
    int lens = strlen(s);
    
    int* arr = (int *)malloc(sizeof(int) * lens);
    int* hash  = (int*)malloc(sizeof(int) * wordssize);
    
    int k = 0;
    hashtable* head = addhash(words, wordssize);  // 构造哈希
    hashtable* out = null;
    for (int i = 0; i < step; ++i) {  // 窗口左侧步进是一个step,所以要遍历一个step里面的左右起点
        int l = i;
        memset(hash, 0, sizeof(int) * wordssize);
        
        for (int r = i; r < lens; r += step) {  // 窗口右侧一个步进、一个步进前进
            char str[step + 1];
            str[0] = '\0';
            strncat(str, s + r, step);  // 截取一个step的字符串、查找
            hash_find_str(head, str, out);
            if(null == out) {   // 未找到,就得重新归零、重新开始,移至下一个元素开头
                memset(hash, 0, sizeof(int) * wordssize);  // 用hash数组代替uthash的增删; 
                l = r + step;                              // hash数组:滑动窗口中个字符串出现的次数!
            } else {  // 窗口中的截取串str在words中出现了,窗口内左侧的子串一定是出现在words里面的!
                int idx = out->idx;
                int cnt = out->cnt;
                hash[idx]++;         // 统计str出现的次数,hash为words的字符串各自出现在窗口中的次数;
                while(hash[idx] > cnt) {    // 在满足条件的结果中:一个word的次数少了,必定导致另外一个word的次数多了
                    char str1[step + 1]; 
                    str1[0] = '\0';
                    strncat(str1, s + l, step);
                    hash_find_str(head, str1, out);
                    hash[out->idx]--;
                    l += step;
                }

                if (r - l + step == lenhash) {  // 窗口匹配后、窗口左侧右移一个step,并hash[idx]--;
                    arr[k++] = l;               // 记录ans结果
                    char str1[step + 1];
                    str1[0] = '\0';
                    strncat(str1, s + l, step);
                    hash_find_str(head, str1, out);
                    hash[out->idx]--;
                    l += step;
                }
            }
        }
    }
    *returnsize = k;
    return arr;
}

c代码:失败案例:哈希表保存重复出现

typedef struct {
    char *str;
    int cnt;
    int idx;
    ut_hash_handle hh;
} hashtable;

hashtable* addhash(char **words, int wordssize) {
    hashtable* head = null;
    hashtable* out = null;
    for (int r = 0; r < wordssize; r++) {
        hash_find_str(head, words[r], out);
        if(null == out) {
            out = (hashtable*)malloc(sizeof(hashtable));
            out->str = words[r];
            out->cnt = 1;
            out->idx = r;
            hash_add_str(head, str, out);
        } else {
            out->cnt++;
        }
    }
    return head;
}

int* findsubstring(char * s, char** words, int wordssize, int* returnsize){
    int step  = strlen(words[0]);
    int lenhash = step * wordssize;
    int lens = strlen(s);
    
    int* arr = (int *)malloc(sizeof(int) * lens);
    int* hash  = (int*)malloc(sizeof(int) * wordssize);
    
    int k = 0;
    hashtable* head = addhash(words, wordssize);
    hashtable* out = null;
    for (int i = 0; i < step; ++i) {  // 遍历初始节点
        int l = i;
        memset(hash, 0, sizeof(int) * wordssize);
        
        for (int r = i; r < lens; r += step) {  // 从初始节点开始,一段一段遍历
            char str[step + 1];
            strncpy(str, s + r, step);
            hash_find_str(head, str, out);
            if(null == out) {   // 未找到,就得重新归零、重新开始,移至下一个元素开头
                memset(hash, 0, sizeof(int) * wordssize);  // 用hash数组代替uthash的增删; 
                l = r + step;                              // hash数组:滑动窗口中个字符串出现的次数!
            } else {
                int idx = out->idx;
                int cnt = out->cnt;
                hash[idx]++;         // 下标出现过、hash[idx]次数
                while(hash[idx] > cnt) {  // 经典的滑动窗口套路,滑动窗口中个字符串出现的次数 > uthash中该字符串出现的次数
                    char str1[step + 1];                    // 窗口就应该收缩左边!直到窗口中字符串次数满足uthash的
                    strncpy(str1, s + l, step);
                    hash_find_str(head, str1, out);
                    hash[out->idx]--;
                    l += step;
                }

                if (r + step - l == lenhash) {  // 窗口匹配后、l右移1个step,并hash[idx]--;
                    arr[k++] = l;         // 记录结果,l并左移一个step;
                    char str1[step + 1];
                    strncpy(str1, s + l, step);
                    hash_find_str(head, str1, out);
                    hash[out->idx]--;
                    l += step;
                }
            }
        }
    }
    *returnsize = k;
    return arr;
}


(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com