http://www.lydsy.com/JudgeOnline/problem.php?id=1030

给出一些单词,问长度为\(m\)的文章有多少文章中出现过任意一个或多个单词.

 

分析


文章总数为\(26^m\),减去没有出现过任意单词的文章数量就是答案.

那么如何求"没有出现过任意单词的文章的数量"呢?

我们用所有单词建立一个AC自动机,那么问题就转化成了在AC自动机上跑\(m\)步(相当于边跑边枚举),不经过单词节点(相当于没有单词成功匹配).在AC自动机上dp即可.

\(dp[i][j]\)表示文章的第\(i\)个字母在自动机的\(j\)号节点上的方案数.那么最终答案就是\(\sum_{i=0}^{sz}dp[m][i]\).

注意\(i\)是从0开始的,因为当走到AC自动机上没有的节点时就会走到0节点.

 

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=6000+5,maxm=100+5,type=26,mod=10007;
 5 int n,m,a=1,b;
 6 int dp[maxm][maxn];
 7 char s[maxm];
 8 struct Aho_Corasick{
 9     int sz,ch[maxn][type],f[maxn],q[maxn];
10     bool val[maxn];
11     Aho_Corasick(){ memset(val,false,sizeof val); }
12     inline void ins(char *s){
13         int u=0,m=strlen(s+1);
14         for(int i=1;i<=m;i++){
15             int c=s[i]-'A';
16             if(!ch[u][c]) u=ch[u][c]=++sz;
17             else u=ch[u][c];
18         }
19         val[u]=true;
20     }
21     inline void get_fail(){
22         int L=1,R=0;
23         for(int c=0;c<type;c++){
24             int u=ch[0][c];
25             if(u){ f[u]=0;q[++R]=u; }
26         }
27         while(L<=R){
28             int u=q[L++];
29             for(int c=0;c<type;c++){
30                 if(!ch[u][c]){ ch[u][c]=ch[f[u]][c]; continue; }
31                 f[ch[u][c]]=ch[f[u]][c];
32                 if(val[ch[f[u]][c]]) val[ch[u][c]]=true;
33                 q[++R]=ch[u][c];
34             }
35         }
36     }
37     inline void DP(int x){
38         for(int i=0;i<=sz;i++){
39             if(val[i]||!dp[x-1][i]) continue;
40             for(int j=0;j<type;j++){
41                 if(!val[ch[i][j]]) dp[x][ch[i][j]]=(dp[x][ch[i][j]]+dp[x-1][i])%mod;
42             }
43         }
44     }
45 }ac;
46 int main(){
47     scanf("%d%d",&n,&m);
48     for(int i=1;i<=n;i++){
49         scanf("%s",s+1);
50         ac.ins(s);
51     }
52     ac.get_fail();
53     dp[0][0]=1;
54     for(int i=1;i<=m;i++) ac.DP(i);
55     for(int i=1;i<=m;i++) a=(a*type)%mod;
56     for(int i=0;i<=ac.sz;i++) b=(b+dp[m][i])%mod;
57     printf("%d\n",(a-b+mod)%mod);
58     return 0;
59 }
View Code

相关文章:

  • 2021-11-19
  • 2022-02-02
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-22
  • 2022-02-14
  • 2021-12-08
猜你喜欢
  • 2021-08-13
  • 2021-07-20
  • 2022-12-23
  • 2022-12-23
  • 2021-08-18
  • 2022-02-14
  • 2022-01-15
相关资源
相似解决方案