字符串-重复的子字符串

42 篇文章 2 订阅
22 篇文章 0 订阅
     力扣题号: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;
}

五、运行结果

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要找到Java中的最长不重复字符串,可以使用滑动窗口算法。滑动窗口是一个可变大小的窗口区域,用于遍历字符串并找到最长的不重复字符串。 以下是一个示例的Java代码实现,可以找到给定字符串的最长不重复字符串: ```java public static String findLongestSubstring(String value) { int max = 0, len = value.length(), temp = 0; HashMap<Character, Integer> map = new HashMap<>(); for(int i = 0; i < len; i++) { int left = map.getOrDefault(value.charAt(i), -1); if(temp >= i - left) { temp = i - left; } else { temp++; max = Math.max(temp, max); } map.put(value.charAt(i), i); } return max; } ``` 这个方法的时间复杂度是O(n),其中n是字符串的长度。空间复杂度是O(1),因为哈希表的大小不取决于输入字符串的长度。 请注意,这段代码中的方法`findLongestSubstring()`返回的是最长不重复字符串的长度,而不是字符串本身。如果你需要返回字符串本身,你可以根据找到的最长长度来提取字符串。 希望这个代码可以帮助到你!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [关于算法:查找字符串中最长的重复字符串所需的Java函数?](https://blog.csdn.net/weixin_42386504/article/details/114521295)[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^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [JAVA练习98-最长不含重复字符的字符串](https://blog.csdn.net/qq_48772498/article/details/122831289)[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^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值