標籤:can cpp main www com 建立 font div set
【題目連結】 http://www.lydsy.com/JudgeOnline/problem.php?id=1030
【題目大意】
求出包含任意一個給定串的串數量
【題解】
我們求出不包含任意一個給定串的數量,用全集去減即可,
對於給定串建立AC自動機,用1節點作為根,0節點向1連全字元集轉移作為超級源,
那麼0->match能匹配所有不包含給定串的串,
記dp[i][j]表示匹配了i長度,匹配到AC自動機j節點的串數量,
統計之後取補集即可。
【代碼】
#include <cstdio>#include <algorithm>#include <cstring> using namespace std;const int N=30010;namespace AC_DFA{ const int Csize=26; int tot,son[N][Csize],sum[N],fail[N],q[N],match[N]; void Initialize(){ memset(match,0,sizeof(int)*(tot+1)); memset(fail,0,sizeof(int)*(tot+1)); memset(sum,0,sizeof(int)*(tot+1)); for(int i=0;i<=tot;i++)for(int j=0;j<Csize;j++)son[i][j]=0; tot=1; } inline int Tr(char ch){return ch-‘A‘;} int Insert(char *s){ int x=1; for(int l=strlen(s),i=0,w;i<l;i++){ if(!son[x][w=Tr(s[i])]){ son[x][w]=++tot; }x=son[x][w]; }sum[x]++; return x; } void MakeFail(){ int h=1,t=0,i,j,x=1; q[++t]=1; while(h<=t)for(x=q[h++],i=0;i<Csize;i++) if(son[x][i]){ fail[son[x][i]]=son[fail[x]][i],q[++t]=son[x][i]; match[son[x][i]]=sum[son[x][i]]?son[x][i]:match[fail[son[x][i]]]; }else son[x][i]=son[fail[x]][i]; }}using namespace AC_DFA;const int P=10007;int dp[110][N];char s[N];void Dp(int x){ for(int i=1;i<=tot;i++){ if(match[i]||!dp[x-1][i])continue; for(int j=0;j<Csize;j++){ int k=i; while(!son[k][j])k=fail[k]; dp[x][son[k][j]]=(dp[x][son[k][j]]+dp[x-1][i])%P; } }}int n,m; int main(){ scanf("%d%d",&n,&m); Initialize(); for(int i=0;i<Csize;i++)son[0][i]=1; for(int i=1;i<=n;i++){scanf("%s",s);Insert(s);} MakeFail(); int ans1=0,ans2=1; dp[0][1]=1; for(int i=1;i<=m;i++)Dp(i); for(int i=1;i<=m;i++)ans2=(ans2*26)%P; for(int i=1;i<=tot;i++)if(!match[i])ans1=(ans1+dp[m][i])%P; printf("%d\n",(ans2-ans1+P)%P); return 0;}
BZOJ 1030 [JSOI2007]文本產生器(AC自動機)