【NC18386】字符串

本文介绍了一种使用双指针(滑动窗口)算法解决字符串问题的方法,通过维护一个字符计数哈希表,找到满足给定条件的最小子串长度。C语言代码展示了如何实现这一过程。
摘要由CSDN通过智能技术生成

题目

字符串

题目又叫字符串,但是这道题是真正的关于字符串的题

思路

这道题可行的我能想出来的思路有两个,一个是二分,先猜测一个答案,然后验证这个答案,但是由于这种方法时间复杂度不如另一种方法:双指针(滑动窗口),所以这里不做记录,只记录双指针的方法:

设置两个指针,一个指针 j j j 标记符合题意的最短字符串的开始,另一个指针 i i i 标记字符串结尾(都是能取到的,闭区间),所以字符串长度就是 i − j + 1 i-j+1 ij+1,初始时两个指针都在字符串开始处 0 0 0,然后让指针 i i i 往前走,直到找出一个符合题意的字符串,此时这个指针标记着字符串的结尾,然后指针 j j j 也开始走,直到走到第一个不符合题意的位置(注意指针所在位置开始的字符串仍然是符合题意的),然后更新答案的值。如此重复即可。

怎么表示一个子串是否符合题意呢?

使用一个哈希表(小写字母常用数组代替哈希表)记录每个字符出现的次数即可,由指针 i i i 遍历到的字符次数加 1 1 1,由指针 j j j 遍历到的字符的次数减 1 1 1(前提是减少之后不为 0 0 0

代码

#include <stdio.h>
#include <string.h>

#define N 1000000 + 5
#define M 26

/**
 * @brief 判断当前子串是不是符合题意的
 *
 * @param st
 * @param len
 * @return int
 */
int check(int* st, int len) {
    for (int i = 0; i < len; i++) {
        if (!st[i]) return 0;
    }
    return 1;
}

/**
 * @brief 计算符合题意的子串最小长度
 *
 * @param s
 * @return int
 */
int solve(const char* s) {
    int i = 0, j = 0, ans = N;
    int st[M] = {0};
    while (s[i]) {
        st[s[i] - 'a']++;
        if (check(st, M)) {
            while (j < i) {
                // 注意只有当移动了 j 之后还符合题意才移动
                if (st[s[j] - 'a'] <= 1) {
                    break;
                }
                st[s[j] - 'a']--;
                j++;
            }
            if (i - j + 1 < ans) {
                ans = i - j + 1;
            }
        }
        i++;
    }
    return ans;
}

int main(void) {
    char s[N];
    scanf("%s", s);
    do {
        if (strlen(s) < M) {
            printf("-114514\n");
            break;
        }
        printf("%d\n", solve(s));
    } while (0);
    return 0;
}
  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渴望力量的猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值