学渣带你刷Leetcode0030串联所有单词的子串

题目描述

给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

 

示例 1:

输入:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:

输入:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
输出:[]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

白话题目:

真难啊,用words中的字符串拼成s中的某一段就好。

算法:

  (1)输入的处理,二维数组存储word

(2)真难啊,C语言啥都得自己实现

1.构造hash表,包含字符串内容和出现的频次;
2.由于可能从第0~wordlen之前作为开始位,需要做开始点的遍历;
3.使用双指针L,R,每次遍历一个单词长度,如果hash表中有单词的计数大于0 ,R指针继续往前跳;失败了就把L跟进;

要是有些词多次出现也属于不行,L也得跟进。

4.核心是R走,消耗hash表,L走遇到hash表里面的值归还。

先看例子

详细解释关注 B站  【C语言全代码】学渣带你刷Leetcode 不走丢 https://www.bilibili.com/video/BV1C7411y7gB

C语言完全代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
// #define MAX_WORDS 10000
struct words
{
    char *word;
    int cnt;
};

int numCount(struct words *hash, int hashNum)  //判断hash表要是都是0就合格了。
{
    int i;
    int allzeros = 0;
    for (i = 0; i < hashNum; i++)
    {
        if (hash[i].cnt > 0)
            allzeros =1;
        if (hash[i].cnt < 0)
            return  -1;
    }
    //printf("numcount is %d\n",allzeros);
    return allzeros;
}

int findInHash(struct words *hash,int hashNum,char *c,int word_len,char Type)  //在没有匹配的时候遇到单词就减少,遇到合格的时候,逐个退出,值加一
{
    int i;
    int findflag = 0;
    for (i = 0; i < hashNum; i++)
    {
        if (strncmp(hash[i].word, c, word_len) == 0)
        {
            if (Type == 'R')
                hash[i].cnt--;
            else
                hash[i].cnt++;
            findflag=1;
            break;
        }
    }
    return findflag;
}

char * substr(char *s,int start,int length)
{
    char  *slice_s = (char *)malloc(sizeof(char) * (length+1));  //不malloc出去就废了  char slice_s[]
    strncpy(slice_s,s+start,length);
    slice_s[length]='\0';
    //puts(slice_s);
    return slice_s;
}


int* findSubstring(char * s, char ** words, int wordsSize, int* returnSize)
{
    //如果输入的数量不行就gameover
    if (s == NULL || wordsSize == 0  || *words == NULL)
    {
        *returnSize = 0;
        return NULL;
    }

    int s_len=strlen(s);
    int Unilength = strlen(words[0]);

    //char *substring=substr(s,0,Unilength);
    // printf("%s ", dest);//

    //C语言得自己写这种hash表 ,内容+数量
    struct words *hash = (struct words*)malloc(sizeof(struct words) * wordsSize);
    int i,j;
    int hashNum=0;

    for (i = 0; i < wordsSize; i++)   //假设3个单词
    {
        for (j = 0; j < hashNum; j++)
        {
            if (hash[j].word && (strcmp(words[i], hash[j].word) == 0))
            {
                hash[j].cnt++;
               printf("word=%s ,hashnum =%d ,cnt =%d\n",hash[j].word,hashNum,hash[j].cnt);
                break;
            }
        }
        if (j == hashNum)   //0的情况在这里
        {
            char *tmp = (char *)malloc(sizeof(char) * Unilength+1);
            strcpy(tmp, words[i]);
            hash[hashNum].word = tmp;
            hash[hashNum].cnt = 1;
            hashNum++;
            printf("word =%s, hashnum =%d,cnt=%d\n",hash[hashNum - 1].word,hashNum,hash[hashNum-1].cnt);  //注意是hasnum-1;
        }
    }

    int count = 0;
    int *ret = (int *)malloc(sizeof(int) * s_len);
    for(i=0; i<Unilength; i++)
    {
        int L=i;
        int R=i;
      //  printf("L= %d,R=%d\n",L,R);
        while(L<=s_len&&R<=s_len)
        {
            //printf("hash数量%d\n",numCount(hash, hashNum));
            int test=numCount(hash,hashNum);
            if(R <= s_len&&numCount(hash, hashNum) > 0 )  //
            {
                if(findInHash(hash,hashNum,&s[R],Unilength,'R'))
                {
                    R=R+Unilength;
                }
                else  //除了吐出来,L要一直到右侧
                {
                    R=R+Unilength;
                    while (L <=s_len && L< R)
                    {
                        findInHash(hash,hashNum,&s[L],Unilength,'L');
                        L += Unilength;
                    }
                }
            }
            else if(R<=s_len&&numCount(hash, hashNum) == 0)
            {
                //printf("结果= %d\n",L);
                ret[count++] = L;
                findInHash(hash,hashNum,&s[L],Unilength,'L');
                L += Unilength;
            }
             else {
                    findInHash(hash,hashNum,&s[L],Unilength,'L');
                         L += Unilength;

            }


        }

    }
    *returnSize=count;
    return ret;
}

int main()
{
    printf("可以输入的s串: xfoofoobarfoobarxx\n");
    char  *s;
    s=(char *)malloc(sizeof(char));
    //scanf("%s",s);  //处理不了空格
    gets(s);

    printf("输入foo bar foo的总个数 3\n");
    int wordsSize;
    scanf("%d",&wordsSize);
    //char* strs[strsSize];  都行
    char **words=(char **)malloc(wordsSize*sizeof(char));
    int m;

    for ( m = 0; m < wordsSize; m ++)      //单词总个数
    {
        words[m]=(char*)malloc(100*sizeof(char));
        scanf("%s",words[m]);   //就是指针的地址
    }
    printf("\n");
    for ( m = 0; m < wordsSize; m ++)
    {
        printf("%s\n",words[m]);
    }

    int returnSize=0;
    int *result=findSubstring( s, words, wordsSize, &returnSize);

    int i;
    for(i=0; i<returnSize; i++)
    {
        printf("------------%d ", result[i]);//
    }

    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,有三方法可以解决LeetCode上的最长回文子串问题。 方法一是使用扩展中心法优化,即从左向右遍历字符串,找到连续相同字符组成的子串作为扩展中心,然后从该中心向左右扩展,找到最长的回文子串。这个方法的时间复杂度为O(n²)。\[1\] 方法二是直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串。这个方法的时间复杂度为O(n³),效率较低。\[2\] 方法三是双层for循环遍历所有子串可能,然后再对比是否反向和正向是一样的。这个方法的时间复杂度也为O(n³),效率较低。\[3\] 综上所述,方法一是解决LeetCode最长回文子串问题的最优解法。 #### 引用[.reference_title] - *1* [LeetCode_5_最长回文子串](https://blog.csdn.net/qq_38975553/article/details/109222153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode-最长回文子串](https://blog.csdn.net/duffon_ze/article/details/86691293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [LeetCode 第5题:最长回文子串(Python3解法)](https://blog.csdn.net/weixin_43490422/article/details/126479629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值