字符串专题

总结关于字符串的常用算法板子

字符串中子串个数

子串可重叠

int f(const std::string& str, const std::string& sub)
{
	int num = 0;
	for (size_t i = 0; (i = str.find(sub, i)) != std::string::npos; num++, i++);
	return num;
}

子串不可重叠

int f(const std::string& str, const std::string& sub)
{
	int num = 0;
	size_t len = sub.length();
	if (len == 0)len=1;//应付空子串调用
	for (size_t i=0; (i=str.find(sub,i)) != std::string::npos; num++, i+=len);
	return num;
}

不同的子序列

[problem description]

给定一个字符串 s,计算 s不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 10^9 + 7 取余

字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。

  • 例如,"ace""abcde" 的一个子序列,但 "aec" 不是。

[input]

s="aba"

[output]

6

[datas]

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

[solved]

dp[i]为前i个字符可以组成的不同的子序列,则有

  • dp[i] = dp[i - 1] + newCount - repeatCoun

newCount为加上 s[i]后新增的子序列个数,repeatCount为重复的子序列个数

我们只需要计算 newCountrepeatCount即可

newCount的值比较好计算,就是 dp[i - 1]

然后我们计算repeatCount,我们观察遍历到的第二个字符b,出现重复的序列为b和ab,而这两个序列正好是上一次添加b(也就是第②步)的时候新增的两个序列。于是我们可以使用数组preCount来记录上一次该字符新增的个数,该个数就是repeatCount。

由于dp[i]仅和dp[i-1]有关,我们可以滚动存储。

[python]

class Solution:
    def distinctSubseqII(self, s: str) -> int:
        mod=10**9+7
        d=defaultdict(int)
        n=len(s)
        cur=1
        for i in range(0,n):
            pre=cur
            cur=((cur+pre)%mod-d[s[i]]+mod)%mod
            d[s[i]]=pre
        return (cur-1+mod)%mod
posted @ 2023-10-24 16:56  White_Sheep  阅读(8)  评论(0编辑  收藏  举报