1397. 找到所有好字符串 (数位dp+KMP)

本文深入探讨了LeetCode上的一道难题——寻找所有好字符串的解决方案。通过使用动态规划和KMP算法,我们详细解释了如何计算在给定两个字符串s1和s2以及一个模式字符串evil的情况下,有多少个字符串既字典序介于s1和s2之间,又不包含evil作为子串。代码中包含了获取KMP失败函数的方法以及主要的动态规划状态转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://leetcode-cn.com/problems/find-all-good-strings/
一句话思路:
d[i][j]代表以字典序小于等于字符串s[0,i]长度位i的字符串为前缀,并且匹配到evil第j个字符(匹配过程用next数组进行失配转移),满足题意的后缀种类数。

typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 500 + 10;
int nxt[maxn];
ll d[maxn][60];
string s,ev;
void get_next(string & ev) {
    int n = ev.length();
    int j = nxt[0] = -1;
    int i = 0;
    while(i < n) {
        if(j == -1 || ev[i] == ev[j]) {
            i++;j++;
            nxt[i] = j;
        }
        else j = nxt[j];
    }
}

int dfs(int cur, int u, bool flag) {
    if(u >= ev.length()) return 0;
    if(cur >= s.length()) return 1;
    if(!flag && ~d[cur][u]) return d[cur][u];
    int li = 'z';
    if(flag) li = s[cur];
    int ret = 0;
    for(char i = 'a'; i <= li; i++) {
        int j = u;
        while(j >= 0 && ev[j] != i) j = nxt[j];
        if(j == -1 || i == ev[j]) j++;
        (ret += dfs(cur + 1, j, flag && (i == li) )) %= mod;
    }
    if(!flag) d[cur][u] = ret;
    return ret;
}

class Solution {
public:
    int findGoodStrings(int n, string s1, string s2, string evil) {
        get_next(evil);
        int ans1, ans2;
        ev = evil;
        memset(d, -1, sizeof(d));
        s = s2;
        ans1 = dfs(0, 0, true);
        s = s1;
        ans2 = dfs(0, 0, true);
        //cout << ans1 << " " << ans2 << endl;
        int ans = (ans1-ans2+mod) % mod;
        if(s1.find(evil) == string::npos) (ans+=1)%=mod;
        return ans;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值