HDU5763 Another Meaning (kmp+dp)
阿新 • • 發佈:2021-10-03
HDU5763 Another Meaning
Mean
給定兩個字串\(A,B\),\(B\)會有兩種表示意思,詢問\(A\)最終有多少種表達方式。
\(T <= 30,|A| <= 100000,|B| <= |A|\)
Sol
\(KMP+DP\).
先做一遍\(B\)串的\(Next\),把\(A\)中所有出現\(B\)的位置標記上(結尾位置)
則\(dp[i]\)表示前\(i\)位能有多少種表達方式.\(dp[0]=1\).
\(if(vis[i]==1)dp[i]=(dp[i-1]+dp[i-lenp])%mod\)
\(else \ dp[i]=dp[i-1]\).
最後直接輸出\(dp[lent]\)
Code
#include<bits/stdc++.h> #define N 100005 using namespace std; char t[N],p[N]; int next1[N]; typedef long long ll; const int mod = 1e9+7; int vis[N]; ll dp[N]; /* KMP + dp */ void get_next(char p[],int lenp){ int j=0; for(int i=2;i<=lenp;++i){ while(j&&p[j+1]!=p[i])j=next1[j]; if(p[j+1]==p[i])j++; next1[i]=j; } } void kmp(char t[],int lent,char p[],int lenp){ int j=0; for(int i=1;i<=lent;++i){ while(j&&p[j+1]!=t[i])j=next1[j]; if(p[j+1]==t[i])j++; if(j==lenp){ vis[i]=1; //cout<<i-lenp+1<<endl;//輸出p在t中出現的位置 } } } void print(int lenp){ for(int i=1;i<=lenp;++i){ cout<<next1[i]<<" "; } } int T; int main(){ scanf("%d",&T); int ca=0; while(T--){ scanf("%s %s",t+1,p+1); int lent=strlen(t+1); int lenp=strlen(p+1); get_next(p,lenp);//預處理p的next陣列 memset(vis,0,sizeof vis); memset(dp,0,sizeof dp); dp[0]=1; kmp(t,lent,p,lenp); for(int i=1;i<=lent;++i){ if(vis[i])dp[i]=(dp[i-1]+dp[i-lenp])%mod; else dp[i]=dp[i-1]; } printf("Case #%d: %lld\n",++ca,dp[lent]); } return 0; } /* */