466 统计重复个数(循环节)

1. 问题描述:

定义 str = [s, n] 表示 str 由 n 个字符串 s 连接构成。
例如,str == ["abc", 3] =="abcabcabc" 。
如果可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。
例如,根据定义,s1 = "abc" 可以从 s2 = "abdbec" 获得,仅需要删除加粗且用斜体标识的字符。
现在给你两个字符串 s1 和 s2 和两个整数 n1 和 n2 。由此构造得到两个字符串,其中 str1 = [s1, n1]、str2 = [s2, n2] 。
请你找出一个最大整数 m ,以满足 str = [str2, m] 可以从 str1 获得。

示例 1:
输入:s1 = "acb", n1 = 4, s2 = "ab", n2 = 2
输出:2

示例 2:
输入:s1 = "acb", n1 = 1, s2 = "acb", n2 = 1
输出:1
提示:
1 <= s1.length, s2.length <= 100
s1 和 s2 由小写英文字母组成
1 <= n1, n2 <= 10 ^ 6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-the-repetitions

2. 思路分析:

首先需要理解题目的意思,题目的主要意思是在S1中按顺序找出最多能有多个S2,本质上是在S1中找子序列的个数,其中S1为n1个s1构成的字符串,S2为n2个s2构成的字符串。最简单的方法是暴力枚举,从前往后扫描S1,在扫描的过程中看能够匹配多少个s2,最后除以n2就是答案,由题目可以知道时间复杂度为10 ^ 8所以可能会超时,我们需要优化一下暴力枚举的,降低一下时间复杂度。对于这种字符串重复的问题我们可以考虑一下循环节。因为字符串是重复的所以我们在S1中匹配s2的时候如果能够判断出当前匹配的位置之前已经匹配过说明存在了重复那么后面字符串的匹配过程是一样的,那么直接计算即可。基于这个想法我们可以在每一段s1中匹配s2,使用k来记录当前匹配s2的个数,当匹配到s2的末尾的时候那么从s2下标从0开始匹配(循环匹配s2),为了能够判断出匹配当前第i段的时候出现了循环节,我们可以使用一个哈希表来记录下每一段s1中匹配s2的位置,也即记录下k % len(s2),如果发现当前的k % len(s2)在哈希表中存在说明出现了循环节,前面的一段0~i-1就是循环节,我们可以直接计算剩下的第i + 1~ n1段能够构成多少个循环节,每个循环节匹配了s2的多少个字符,相乘就是剩余的这么多段s1能够匹配s2的字符数目,计算一开始的第一个循环节与剩余不满足一个循环节匹配的s2的字符个数,将这些结果累加起来就是在n1个s1中匹配s2的字符个数,最后除以(len(s2) * n2) 那么就是最终的答案。

3. 代码如下:

class Solution:
    def getMaxRepetitions(self, s1: str, n1: int, s2: str, n2: int) -> int:
        dic = dict()
        # k表示到目前为止匹配了多少个s2中的字符
        k = 0
        res = 0
        # count记录到当前的第i段匹配的s2的字符个数
        count = list()
        t = 0
        # 第一层循环表示是第i段的s1
        for i in range(n1):
            for j in range(len(s1)):
                if s1[j] == s2[k % len(s2)]:
                    k += 1
            count.append(k)
            # 说明出现了循环节, 也即完全匹配了s2, 可能包含多个s2
            if k % len(s2) in dic:
                # 当前循环节有i段s1
                a = i
                # b为循环节匹配的s2的字符个数
                b = k - count[0]
                # 计算剩余的这么多段能够匹配的s2的字符个数
                res += (n1 - i - 1) // a * b
                # 计算剩余的不满足循环节的匹配的s2的字符个数
                for u in range((n1 - i - 1) % i):
                    for j in range(len(s1)):
                        if s1[j] == s2[k % len(s2)]: k += 1
                # res当前记录的是匹配了多少了s2的字符
                res += k
                return res // len(s2) // n2
            # 标记每一段匹配s2的位置
            dic[k % len(s2)] = i
        if not count: return 0
        return count[-1] // len(s2) // n2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一个汇编语言程序,用于统计字符串中字符的个数。以下是示例代码: ``` section .data string db 'Hello, world!',0 section .bss count resb 26 section .text global _start _start: xor ecx, ecx ; clear ECX register mov esi, string ; load address of string into ESI register count_loop: mov eax, [esi] ; load next character from string into EAX register cmp eax, 0 ; check if end of string je end_loop cmp eax, 'a' ; check if character is between 'a' and 'z' jl not_lowercase cmp eax, 'z' jg not_lowercase sub eax, 'a' ; convert lowercase character to index inc byte [count + eax] ; increment count for that character not_lowercase: inc esi ; move to next character inc ecx ; increment character count jmp count_loop end_loop: ; print character counts for each lowercase letter mov esi, count mov ecx, 26 print_loop: movzx eax, byte [esi] push eax push dword 'a' mov eax, 4 mov ebx, 1 mov ecx, esp mov edx, 2 int 0x80 add esp, 8 inc esi loop print_loop ; exit program mov eax, 1 xor ebx, ebx int 0x80 ``` 该程序首先定义一个字符串(在`.data`中),然后在`.bss`中定义了一个26字的计数器数组(用于计算每个小写字母的出现次数)。程序使用ECX寄存器计算字符串中的字符总数,并使用ESI寄存器跟踪当前字符的地址。在循环中,程序检查当前字符是否为小写字母,并将其转换为小写字母计数器数组中的索引。然后,程序将该字符的计数器递增,然后移动到下一个字符并重复此过程,直到字符串的结尾。 最后,程序使用`int 0x80`系统调用打印每个小写字母的计数器值,并使用`int 0x80`调用退出程序。 请注意,此示例程序仅计算小写字母的频率,并且假定字符串以null字符结尾。如果您需要计算其他字符的频率,或者字符串以不同的方式终止,请相应地更改程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值