CF494B Obsessive String(KMP+DP)
阿新 • • 發佈:2020-09-08
題意:
詢問從一個母串裡找出數量大於等於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; }