1 solutions
-
0
难度: 紫(虚高)
算法: AC 自动机,或其它字符串算法
挺简单的。
先把所有字符串插入 AC 自动机。
然后和二次加强版差不多,把每个串当作文本串放进去匹配一遍最后再加起来就好了。
#include<bits/stdc++.h> using namespace std; int n; char s[210][1000100]; int tr[1000100][26],fa[1000100],in[1000100],en[1000100],cnt[1000100],c; queue<int> q; void ins(int x){ int u=0; int m=strlen(s[x]); for(int i=0;i<m;i++){ if(tr[u][s[x][i]-'a']==0){ tr[u][s[x][i]-'a']=++c; } u=tr[u][s[x][i]-'a']; } en[x]=u; } void build(){ for(int i=0;i<26;i++){ if(tr[0][i]) q.push(tr[0][i]); } while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<26;i++){ if(tr[u][i]){ fa[tr[u][i]]=tr[fa[u]][i]; q.push(tr[u][i]); } else tr[u][i]=tr[fa[u]][i]; } } } void que(int x){ int m=strlen(s[x]); int u=0; for(int i=0;i<m;i++){ u=tr[u][s[x][i]-'a']; cnt[u]++; } } void tpo(){ for(int i=1;i<=c;i++) in[fa[i]]++; for(int i=1;i<=c;i++){ if(in[i]==0) q.push(i); } while(!q.empty()){ int u=q.front(); q.pop(); int v=fa[u]; in[v]--; cnt[v]+=cnt[u]; if(in[v]==0) q.push(v); } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s[i]); ins(i); } build(); for(int i=1;i<=n;i++){ que(i); } tpo(); for(int i=1;i<=n;i++){ printf("%d\n",cnt[en[i]]); } }
- 1
Information
- ID
- 62
- Time
- 1000ms
- Memory
- 512MiB
- Difficulty
- 10
- Tags
- # Submissions
- 3
- Accepted
- 3
- Uploaded By