hdu 4758 AC自動機+狀壓
阿新 • • 發佈:2018-11-14
這道題卡了好幾天,然後發現狀態寫錯的,dp[i][j][k][x]表示走到(i,j)點在AC自動機上第K個點狀態為X的步數,有狀態K是因為要求必須包含這兩種狀態,有一點不怎麼明白,這道題應該是能用到這兩個字串的方案數,比如說用2.5個第一種和1個第二種這種應該也是可以的。要不然最後統計答案的時候就沒法解釋了…
#include<bits/stdc++.h> using namespace std; using LL = int64_t; const int maxnode=205; const int sigma_size=2; const LL mod=1e9+7; char s[maxnode]; int dp[105][105][205][4]; struct Node { int son[sigma_size]; int val,fail; }ch[maxnode]; struct AC { int sz=1; queue<int>Q; void init(int x) {ch[x].fail=ch[x].val=0;memset(ch[x].son,0,sizeof(ch[x].son));} int idx(char c) { if(c=='D') return 0; if(c=='R') return 1; } void insert(char s[],int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u].son[c]) { init(sz); ch[u].son[c]=sz++; } u=ch[u].son[c]; } ch[u].val=v; } void build() { for(int i=0;i<sigma_size;i++) if(ch[0].son[i]) Q.push(ch[0].son[i]); while(!Q.empty()) { int now=Q.front();Q.pop(); int fail=ch[now].fail; for(int i=0;i<sigma_size;i++) { int nxt=ch[now].son[i]; if(nxt) { ch[nxt].fail=ch[fail].son[i]; Q.push(nxt); } else ch[now].son[i]=ch[fail].son[i]; ch[ch[now].son[i]].val|=ch[ch[ch[now].fail].son[i]].val; } } } int solve(int n,int m) { for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) { for(int k=0;k<sz;k++) { for(int x=0;x<=3;x++) { dp[i][j][k][x]=0; } } } } dp[0][0][0][0]=1; for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) { for(int k=0;k<sz;k++) { for(int x=0;x<4;x++) { if(dp[i][j][k][x]>0) { dp[i+1][j][ch[k].son[0]][x|ch[ch[k].son[0]].val]=(dp[i+1][j][ch[k].son[0]][x|ch[ch[k].son[0]].val]+dp[i][j][k][x])%mod; dp[i][j+1][ch[k].son[1]][x|ch[ch[k].son[1]].val]=(dp[i][j+1][ch[k].son[1]][x|ch[ch[k].son[1]].val]+dp[i][j][k][x])%mod; } } } } } LL ans=0; for(int i=0;i<sz;i++) ans=(ans+dp[n][m][i][3])%mod; return ans; } }; int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int T;cin>>T; while(T--) { AC ans;ans.init(0); int n,m;cin>>n>>m; cin>>s;ans.insert(s,1); cin>>s;ans.insert(s,2); ans.build(); cout<<ans.solve(m,n)<<"\n"; } return 0; }