http://www.elijahqi.win/archives/3273
题意:给定k种类型 每种类型里有一定数量的串
求给定串中 k种类型按照顺序出现的方案数 只要位置不同或者在这个类型里属于不同的两种串即算不同答案
hash预处理 dp[i][j]表示当前在待匹配串的i位置 我现在属于第j种串的结尾我的总答案是多少
1e7枚举状态转移即可
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll unsigned long long
#define lle long long
using namespace std;
const int g1=1000003;
const int g2=100003;
const int N=10010;
const int mod=1000000007;
ll p1[N],p2[N],hs1[N],hs2[N],hst1[110][11],hst2[110][11];
char s[N],s1[N];
int nm[110],len[110][11],k;
lle dp[N][110];
inline bool judge(int l,int r,int kd,int d){
ll tmp1,tmp2;
tmp1=hs1[r]-hs1[l]*p1[r-l];tmp2=hs2[r]-hs2[l]*p2[r-l];
return (tmp1==hst1[kd][d])&&(tmp2==hst2[kd][d]);
}
int main(){
freopen("str.in","r",stdin);
freopen("str.out","w",stdout);
scanf("%d",&k);scanf("%s",s+1);
int n=strlen(s+1);p1[0]=1;p2[0]=1;
for (int i=1;i<=n;++i) p1[i]=p1[i-1]*g1,p2[i]=p2[i-1]*g2,
hs1[i]=hs1[i-1]*g1+s[i],hs2[i]=hs2[i-1]*g2+s[i];
for (int owo=1;owo<=k;++owo){
int kd;scanf("%d",&kd);nm[owo]=kd;
for (int j=1;j<=kd;++j){
scanf("%s",s1+1);static ll tmp1,tmp2;tmp1=tmp2=0;
int le=strlen(s1+1);len[owo][j]=le;
for (int i=1;i<=le;++i){
tmp1=tmp1*g1+s1[i];
tmp2=tmp2*g2+s1[i];
}hst1[owo][j]=tmp1;hst2[owo][j]=tmp2;
}
}for (int i=0;i<=n;++i) dp[i][0]=1;
for (int i=1;i<=n;++i){
for (int kd=1;kd<=k;++kd){int tmp=0;
for (int j=1;j<=nm[kd];++j){
if (i-len[kd][j]<0) continue;
if (judge(i-len[kd][j],i,kd,j)) tmp+=dp[i-len[kd][j]][kd-1];tmp%=mod;
}dp[i][kd]=tmp;
}
}lle ans=0;
for (int i=1;i<=n;++i) ans+=dp[i][k],ans%=mod;
printf("%lld\n",ans);
return 0;
}