1. 程式人生 > 實用技巧 >CF494B Obsessive String(KMP+DP)

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\n",dp[n]),0; }