不用AC自动机的话,怎么dp,推公式都会交叉,都会重复,只有用AC自动机分离出一个个匹配的状态才能解决
此题是poj2778 DNA sequence的弱化版
1.对自动机上每个状态dp,dp[a][b][c][d]表示经过了a个字符,匹配了b个R,在c这个状态,d是4进制数,表示是否经过串1和串2
trie树上其实代表一种转移关系,即当前匹配了i个字符,遇到i+1个字符会转到哪个状态
2.深刻理解fail指针,点u的fail指针,即到达状态u,也就到达状态fail[u],所以val[u]|=val[fail[u]]
在求fail要用到一个优化,补齐不存在的边,直接fail[ch[u][i]]=ch[fail[u]][i],不用while(p&&!ch[p][i]) p=fail[p],那样很慢
考虑现在状态u上,下个字符是R,R边存在,u状态上的值直接加到与R边相连的儿子;
如果下个字符时D,D边不存在,u的下个状态nxt,是u沿着失配指针一直走,途中经过很多状态p,某个p的D边存在,这个p就是nxt;
假如有这个优化就不用每次while(p&&!ch[p][i]) p=fail[p]一直走,不然会TLE
卡着时间过,用指针版会快点
#include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <algorithm> using namespace std; #define mod 1000000007 #define ll long long #define CH 2 #define N 250 int ch[N][CH],fail[N],sz,val[N],que[N],sw[300]; ll dp[2][N/2][N][4]; void _insert(char *s,int idx) { int p=0; for(int i=0;s[i]!='\0';++i) { if(ch[p][sw[s[i]]]==0) ch[p][sw[s[i]]]=sz++; p=ch[p][sw[s[i]]]; } val[p]=idx; } void getfail() { int front=0,rear=0; for(int i=0;i<CH;++i) if(ch[0][i]) { que[rear++]=ch[0][i]; fail[ch[0][i]]=0; } while(front<rear) { int u=que[front++]; for(int i=0;i<CH;++i) if(ch[u][i]) { que[rear++]=ch[u][i]; fail[ch[u][i]]=ch[fail[u]][i]; val[ch[u][i]]|=val[ch[fail[u]][i]]; } else ch[u][i]=ch[fail[u]][i]; } } void init() { memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); sz=1; } char str[200]; int m,n; int main () { sw['R']=0;sw['D']=1; int T;scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); init(); scanf("%s",str); _insert(str,1); scanf("%s",str); _insert(str,2); getfail(); memset(dp,0,sizeof(dp)); dp[0][0][0][0]=1; for(int tt=0;tt<m+n;++tt) // tt -> tt+1 { memset(dp[(tt+1)%2],0,sizeof(dp[(tt+1)%2])); for(int sta=0;sta<sz;++sta) { for(int j=0;j<=m;++j) for(int r=0;r<4;++r) { for(int k=0;k<CH;++k) { int mm=k==0?1:0; // sw['R']=0 int nxt=ch[sta][k]; dp[(tt+1)%2][j+mm][nxt][r|val[nxt]]+=dp[tt%2][j][sta][r]; if( dp[(tt+1)%2][j+mm][nxt][r|val[nxt]]>=mod) dp[(tt+1)%2][j+mm][nxt][r|val[nxt]]%=mod; } } } } ll ans=0; for(int i=0;i<sz;++i) { ans+=dp[(m+n)%2][m][i][3]; if(ans>=mod) ans%=mod; } cout<<ans<<endl; } return 0; }