CF494B Obsessive String(KMP+DP)

题意:

询问从一个母串里找出数量大于等于1的子串,且每个子串互不重合,都包含指定的模式串t,有多少种找法。

题解:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
const int mod=1e9+7;
typedef long long ll;
ll dp[maxn];
ll sum[maxn];
ll pre[maxn];
ll nxt[maxn];
char s1[maxn];
char s2[maxn];
vector<int> kmp (char * s1,char * s2) {
    nxt[0]=nxt[1]=0;
    vector<int> v;
    int len1=strlen(s1);
    int len2=strlen(s2);
    int k=0;
    for (int i=1;i<len1;i++) {
        while (k&&s2[i]!=s2[k]) k=nxt[k];
        nxt[i+1]=s2[i]==s2[k]?++k:0;
    }
    k=0;
    for (int i=0;i<len1;i++) {
        while (k&&s1[i]!=s2[k]) k=nxt[k];
        k+=s1[i]==s2[k]?1:0;
        if (k==len2) {
            v.push_back(i-len2+2);
            pre[i+1]=v.back();
        }
    }
    for (int i=1;i<=len1;i++) if (!pre[i]) pre[i]=pre[i-1];
    return v;
}
int main () {
    cin>>s1;
    cin>>s2;
    int n=strlen(s1);
    vector<int> v=kmp(s1,s2);
    for (int i=1;i<=n;i++) {
        dp[i]=dp[i-1];
        if (pre[i]) {
            dp[i]=(dp[i]+sum[pre[i]-1]+pre[i])%mod;
        }
        sum[i]=(sum[i-1]+dp[i])%mod;
    }
    return printf("%lld
",dp[n]),0;
}
原文地址:https://www.cnblogs.com/zhanglichen/p/13635128.html