Connie 題解(dp+kmp)
阿新 • • 發佈:2021-08-13
題目連結
題目思路
設\(dp[i][j]\)表示已經構造了\(T\)的前\(i\)位,用\(S\)去\(kmp\)匹配\(T\),到第\(i\)位時,\(kmp\)匹配到\(S\)的第\(j\)位,列舉\(i+1\)位選了啥
然後用\(nxt\)陣列往回跳,這個最差暴力往回跳的複雜度為\(O(m)\) 可以維護一個\(nx[i][j]\)表示第\(i\)個位置後面如果接\(j\)會
跳到哪裡,這樣維護\(j\)的複雜度為\(O(1)\)
但資料小暴力\(nxt\)複雜度可以過去
程式碼
卷也卷不過,躺又躺不平#include<bits/stdc++.h> #define fi first #define se second #define debug cout<<"I AM HERE"<<endl; using namespace std; typedef long long ll; const int maxn=1e2+5,inf=0x3f3f3f3f,mod=998244353; const double eps=1e-6; int n,m; int nxt[maxn]; ll dp[maxn][maxn]; char s[maxn],c[]={' ','c','o','n','i','e'}; ll qpow(ll a,ll b){ ll ans=1,base=a; while(b){ if(b&1) ans=ans*base%mod; base=base*base%mod; b=b>>1; } return ans; } void getnext(){ for(int i=2,j=0;i<=m;i++){ while(j&&s[i]!=s[j+1]){ j=nxt[j]; } if(s[i]==s[j+1]) j++; nxt[i]=j; } } signed main(){ scanf("%d%d",&n,&m); scanf("%s",s+1); getnext(); dp[0][0]=1; for(int i=0;i<=n;i++){ for(int j=0;j<=m;j++){ for(int k=1;k<=5;k++){ int pos=j; while(pos&&(s[pos+1]!=c[k])) pos=nxt[pos]; if(c[k]==s[pos+1]) pos++; dp[i+1][pos]=(dp[i+1][pos]+dp[i][j]*(pos==m?2:1))%mod; } } } ll ans=0; for(int i=0;i<=m;i++){ ans+=dp[n][i]; } ans=ans%mod*qpow(qpow(5,n),mod-2)%mod; printf("%lld\n",ans); return 0; }