[cf1483F]Exam

对于字符串$s_{i}$,考虑(作为$s_{i}$的子串)与$s_{i}$有贡献的$s_{j}$

枚举$s_{i}$的前缀$t$,考虑所有是$t$后缀的$s_{j}$,显然仅有其中最长的可能有贡献

建立ac自动机,那么$s_{j}$即该前缀跳fail指针时第一个结束节点,可以预处理出

同时,注意到$s_{j}$有贡献当且仅当满足以下条件:

1.不存在其余被找到的串,使得其所在的区间包含$s_{j}$(维护左端点即可)

2.对于所有能跳fail指针能跳到$s_{j}$的前缀,均跳到了$s_{j}$(对两者分别计数,前者即子树求和)

时间复杂度为$o(n\log n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000005
 4 #define D 26 
 5 queue<int>q;
 6 vector<int>pos[N],e[N];
 7 int n,V,l,ans,ed[N],dep[N],ch[N][D],nex[N],dfn[N],sz[N],Pos[N],cnt[N];
 8 char s[N];
 9 struct TA{
10     int f[N];
11     int lowbit(int k){
12         return (k&(-k));
13     }
14     void update(int k,int x){
15         while (k<=V){
16             f[k]+=x;
17             k+=lowbit(k);
18         }
19     }
20     int query(int k){
21         int ans=0;
22         while (k){
23             ans+=f[k];
24             k-=lowbit(k);
25         }
26         return ans;
27     }
28 }T;
29 void dfs(int k){
30     dfn[k]=++dfn[0],sz[k]=1;
31     for(int i=0;i<e[k].size();i++){
32         if (!ed[e[k][i]])ed[e[k][i]]=ed[k];
33         dfs(e[k][i]),sz[k]+=sz[e[k][i]];
34     }
35 }
36 int main(){
37     scanf("%d",&n),V=1;
38     for(int i=1;i<=n;i++){
39         scanf("%s",s+1),l=strlen(s+1);
40         int k=1;
41         for(int j=1;j<=l;j++){
42             if (!ch[k][s[j]-'a']){
43                 ch[k][s[j]-'a']=++V;
44                 dep[V]=dep[k]+1;
45             }
46             k=ch[k][s[j]-'a'],pos[i].push_back(k);
47         }
48         ed[k]=k;
49     }
50     for(int i=0;i<D;i++)
51         if (ch[1][i])nex[ch[1][i]]=1,q.push(ch[1][i]);
52     while (!q.empty()){
53         int k=q.front();
54         q.pop();
55         for(int i=0;i<D;i++)
56             if (ch[k][i]){
57                 int j=nex[k];
58                 while ((j>1)&&(!ch[j][i]))j=nex[j];
59                 if (ch[j][i])j=ch[j][i];
60                 nex[ch[k][i]]=j,q.push(ch[k][i]);
61             }
62     }
63     for(int i=2;i<=V;i++)e[nex[i]].push_back(i);
64     dfs(1);
65     for(int i=1;i<=n;i++){
66         int t=0,mn=1e9;
67         reverse(pos[i].begin(),pos[i].end());
68         for(int j=0;j<pos[i].size();j++){
69             int k=pos[i][j],x=ed[k];
70             if (!j)x=ed[nex[k]];
71             if (!x)continue;
72             if (!cnt[x])Pos[++t]=x;
73             cnt[x]++;
74             if (mn<=dep[k]-dep[x])cnt[x]=-1e9;
75             else mn=dep[k]-dep[x];
76         }
77         for(int j=0;j<pos[i].size();j++)T.update(dfn[pos[i][j]],1);
78         for(int j=1;j<=t;j++){
79             int k=Pos[j];
80             if (T.query(dfn[k]+sz[k]-1)-T.query(dfn[k]-1)==cnt[k])ans++;
81             cnt[k]=0;
82         }
83         for(int j=0;j<pos[i].size();j++)T.update(dfn[pos[i][j]],-1);
84     }
85     printf("%d\n",ans);
86     return 0;
87 }
View Code

 

posted @ 2022-02-14 19:09  PYWBKTDA  阅读(54)  评论(0编辑  收藏  举报