提议大致是给n,m,再给两个非空的不相同的只包含R或D字符串s1,s2,问用n个R,m个D可以组成多少种包含s1,s2的字符串。大致思路的话,先根据两个字符串构造trie图,其实就是把失配函数优化掉的ac自动机。之后用dp[i][x][y][k]表示在自动机上状态i,用x个R,y个D,包含s1,s2的状态.令初值dp[0][0][0][0]=1,向上DP,最后统计dp[i][n][m][3](0<=i<top)的和即可。
#include <iostream> #include <algorithm> #include <cstdio> #include <memory.h> #include <string> #include <cstring> #include <queue> using namespace std; typedef long long ll; const int maxn=420; const int tk=2; int tree[maxn][tk]; int val[maxn]; int last[maxn]; int f[maxn]; int n,m,p,q,k; int top; int dp[220][110][110][4]; int ok[maxn]; const int mod=1000000007; inline int idx(char s) { if (s=='R') return 0; return 1; } struct autoAC { void init() { top=1; tree[0][0]=tree[0][1]=0; memset(val,0,sizeof val); memset(f,0,sizeof f); memset(last,0,sizeof last); } void insert(char* s,int rank) { int rt,nxt; for (rt=0; *s; rt=nxt,++s) { nxt=tree[rt][idx(*s)]; if (nxt==0) { tree[rt][idx(*s)]=nxt=top; tree[top][0]=tree[top][1]=0; top++; } } val[rt]=rank; } void getFail() { queue<int> q; f[0]=0; for (int c=0; c<tk; c++) { int u=tree[0][c]; if (u) { q.push(u); f[u]=0; last[u]=0; } } while(!q.empty()) { int r=q.front(); q.pop(); for (int c=0; c<tk; c++) { int u=tree[r][c]; if (!u) { tree[r][c]=tree[f[r]][c]; continue; } q.push(u); int v=f[r]; while(v && !tree[v][c]) v=f[v]; f[u]=tree[v][c]; last[u]=val[f[u]]? f[u] : last[f[u]]; } } } }ac; int tt; int mx,my; char s[105],ss[105],str[105]; inline void work() { memset(ok,0,sizeof ok); for (int i=0; i<top; i++) { int j=last[i]; ok[i]=val[i]; while(j) { ok[i]=ok[i]|val[j]; j=last[j]; } } dp[0][0][0][0]=1; int sta; for (int x=0; x<=mx; x++) for (int y=0; y<=my; y++) for (int i=0; i<top; i++) for (int k=0; k<4; k++) { if (dp[i][x][y][k]==0) continue; if (x<mx) { int nxt=tree[i][0]; sta=k|ok[nxt]; dp[nxt][x+1][y][sta]+=dp[i][x][y][k]; if (dp[nxt][x+1][y][sta]>=mod) dp[nxt][x+1][y][sta]-=mod; } if (y<my) { int nxt=tree[i][1]; sta=k|ok[nxt]; dp[nxt][x][y+1][sta]+=dp[i][x][y][k]; if (dp[nxt][x][y+1][sta]>=mod) dp[nxt][x][y+1][sta]-=mod; } } ll res=0; for (int i=0; i<top; i++) { res+=dp[i][mx][my][3]; // if (res>=mod) res-=mod; } res%=mod; cout<<res<<endl; } int main() { // freopen("in.txt","r",stdin); scanf("%d",&tt); while(tt--) { ac.init(); scanf("%d%d",&mx,&my); for (int i=1; i<=2; i++) { scanf("%s",s); ac.insert(s,i); } ac.getFail(); memset(dp,0,sizeof dp); work(); } return 0; }