首页 > 其他分享 >字符串-重复的子字符串

字符串-重复的子字符串

时间:2024-06-03 18:04:19浏览次数:30  
标签:pat 重复 Next char int str 字符串

     力扣题号:459. 重复的子字符串

一、题目描述

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

二、示例

示例 1:

输入: s = "abab"
输出: true
解释: 可由子串 "ab" 重复两次构成。

示例 2:

输入: s = "aba"
输出: false

示例 3:

输入: s = "abcabcabcabc"
输出: true
解释: 可由子串 "abc" 重复四次构成。 (或子串 "abcabc" 重复两次构成。)

提示:

  • 1 <= s.length <= 104
  • s 由小写英文字母组成

三、求解思路

四、代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <iostream>

using namespace std;

int KMPSearch(char* pat, char* txt);
void computeNextArray(char* pat, int M, int* Next);

// 暴力求解法
int bruteForce(char* str) {
    int len = strlen(str);
    // 遍历所有可能的子串长度
    for (int sub_len = 1; sub_len <= len / 2; ++sub_len) {
        // 如果字符串长度不能被子串长度整除,则该子串不可能构成原字符串
        if (len % sub_len != 0)
            continue;

        // 提取子串
        char *substring = (char*)malloc((len + 1)*sizeof(char));
        strncpy(substring, str, sub_len);
        substring[sub_len] = '\0';

        // 初始计数器,用于记录通过重复子串构造了多少次
        int count = 1;
        // 指向当前比较位置的指针
        const char* ptr = str + sub_len;

        // 尝试用子串匹配整个字符串
        while (*ptr != '\0') {
            if (strncmp(ptr, substring, sub_len) == 0) {
                ptr += sub_len;
                ++count;
            }
            else {
                break; // 不匹配,跳出循环
            }
        }

        // 如果整个字符串都能由子串构成,且刚好用完子串次数,返回1
        if (*ptr == '\0' && count * sub_len == len)
            return 1;
    }

    // 如果没有找到合适的子串,返回0
    return 0;
}

// 移动匹配法
int Moving_matching(char* str) {
    int len = strlen(str);
    char* str2 = (char*)malloc((2 * len - 1) * sizeof(char));
    str2[2 * len - 2] = '\0';

    // 合并两个相同的字符串
    char* p = str + 1;
    char* p2 = str2;
    while (*p) {
        *p2++ = *p++;
    }
    p = str;
    while (*p && *p2) {
        *(p2++) = *(p++);
    }

    // 使用KMP算法进行匹配
    int res = KMPSearch(str, str2);
    return  res == -1 ? 0: 1;
}

// KMP求解法
int KMP_Solutuon(char* str) {
    int len = strlen(str);

    // 计算Next数组。
    int* Next = (int*)malloc(len * sizeof(int));
    computeNextArray(str, len, Next);
    
    if (Next[len - 1] != 0 && len % (len - (Next[len - 1])) == 0) {
        return 1;
    }
    return 0;
}

// 构建next数组
void computeNextArray(char* pat, int M, int* Next) {
    int j = 0;
    Next[0] = 0;
    for (int i = 1; i < M; i++) {

        // 前后缀不匹配
        while (j > 0 && pat[i] != pat[j]) {
            j = Next[j - 1];
        }
        // 前后缀匹配
        if (pat[i] == pat[j]) {
            j++;
        }
        Next[i] = j;
    }
}



// KMP字符串匹配
int KMPSearch(char* pat, char* txt) {
    int M = strlen(pat);
    int N = strlen(txt);

    int* Next = (int*)malloc(M * sizeof(int));
    computeNextArray(pat, M, Next);

    int i = 0; // 文本串指针
    int j = 0; // 模式串指针

    while (i < N) {
        if (pat[j] == txt[i]) {
            j++;
            i++;
        }
        if (j == M) {
            return i - j; // 匹配成功
        }
        else if (i < N && pat[j] != txt[i]) {
            if (j != 0) {
                j = Next[j - 1];
            }
            else {
                i++;
            }
        }
    }

    return -1; // 未找到匹配
}

int main() {

    char str[1000] = { 0 };
    char pat[1000] = { 0 };
    fgets(str, 1000, stdin); // 获取一个字符串
    int length = strlen(str);
    str[length - 1] = '\0';

    cout << "暴力求解:" << bruteForce(str) << endl;

    cout << "移动匹配求解:" << Moving_matching(str) << endl;

    cout << "KMP求解:" << KMP_Solutuon(str) << endl;

    return 0;
}

五、运行结果

标签:pat,重复,Next,char,int,str,字符串
From: https://blog.csdn.net/qq_53436105/article/details/139420914

相关文章

  • std::numeric_limits::max和宏定义重复报错问题
    std::numeric_limits::max和宏定义重复报错问题问题描述今天在编译BeckhoffADS开源组件的时候发现编译报错,报错代码如下longAdsDevice::ReadReqEx2(uint32_tgroup,uint32_toffset,size_tlength,void*buffer,uint32_t*bytesRead)const{if(length>std::nume......
  • AOP简化公共属性create_time,create_user,update_time,update_user记录的重复代码
    处理这些公共字段,需要在每一个业务方法中进行操作,编码相对冗余、繁琐使用AOP切面编程,实现功能增强,来完成公共字段自动填充功能。1.2实现思路在实现公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重......
  • 论文降重秘诀:4种技巧降低AIGC论文的重复率?
    如何有效降低AIGC论文的重复率,也就是我们说的aigc如何降重?AIGC疑似度过高确实是个比较愁人的问题。如果你用AI帮忙写了论文,就一定要在交稿之前做一下AIGC降重的检查。一般来说,如果论文的AIGC超过30%,很可能会被判定为AI代写,从而无法参加答辩,影响毕业。那么如何降低AIGC的疑似度......
  • python对excel文件中指定表格的指定列数据进行去重复操作。
    importpandasaspd#读取Excel文件df_all=pd.read_excel('域名管理系统.xlsx',sheet_name=None,engine='openpyxl')#确保'01流水'表存在if'01流水'indf_all:#提取第1列第2行至第1000行的数据并去重df_two=df_all['01流水']un......
  • Java中字符串格式化的参数索引用法
    Java中字符串格式化是通过String类的format()方法来实现的,该方法有两种定义:publicstaticStringformat(Stringformat,                           Object...args)publicstaticStringformat(Localel,                  ......
  • Java中字符串格式化的短横线标志用法
    Java中字符串格式化是通过String类的format()方法来实现的,该方法有两种定义:publicstaticStringformat(Stringformat,                           Object...args)publicstaticStringformat(Localel,                  ......
  • Java中字符串格式化的井号标志用法
    Java中字符串格式化是通过String类的format()方法来实现的,该方法有两种定义:publicstaticStringformat(Stringformat,                           Object...args)publicstaticStringformat(Localel,                  ......
  • Java中字符串格式化的语法
     产生格式化输出的每个方法都需要格式字符串和参数列表。格式字符串是一个String,它可以包含固定文本以及一个或多个嵌入的格式说明符。请考虑以下示例:Calendarc=...;Strings=String.format("Duke'sBirthday:%1$tm%1$te,%1$tY",c);   Java语言的格式化输出在很......
  • js中将小/大驼峰格式的字符串转为下划线相连的字符串
    functionisUpperCase(ch){ return/^[A-Z]$/.test(ch)}functionisLowerCase(ch){ return/^[a-z]$/.test(ch)}functionconvert(str){ letarr=[]; for(i=0;i<str.length;i++) { constpreSmall=i>0?isLowerCase(str[i-1]):false; /......
  • 程序分享--常见算法/编程面试题:删除有序数组中的重复项 II
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;有意找工作的同学,请参考博主的原创:《面试官心得--面试前应该如何准备》,《面试官心得--面试时如何进行自我介绍》, 《做好面试准备,迎接2024金三银四》。或关注博主免费专栏【程序......