BZOJ 2754 [SCOI2012]喵星球上的点名
2016-09-27 13:56
525 查看
AC自动机
对每一个询问串建AC自动机,拿每一个名字跑AC自动机,不断在fail指针上统计答案即可。因为字符串总长度有保证,时间复杂度可以近似看成O(LEN)。
刚开始比较SB,每一个trie节点都开了一个next[10000],结果MLE了。实际上每个节点根本用不到这么多,可以改成map。
做fail指针的时候不用从1扫到10000来找子节点,因为子节点并没有那么多,可以把子节点的编号用vector记录下来,要不然应该会T。
对每一个询问串建AC自动机,拿每一个名字跑AC自动机,不断在fail指针上统计答案即可。因为字符串总长度有保证,时间复杂度可以近似看成O(LEN)。
刚开始比较SB,每一个trie节点都开了一个next[10000],结果MLE了。实际上每个节点根本用不到这么多,可以改成map。
做fail指针的时候不用从1扫到10000来找子节点,因为子节点并没有那么多,可以把子节点的编号用vector记录下来,要不然应该会T。
#include<cstdio> #include<vector> #include<queue> #include<map> #include<cstring> #define N 20005 #define M 50005 #define NUM 10005 #define LEN 1000005 using namespace std; int in() { int r=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9')r=r*10+c-'0',c=getchar(); return r; } vector<int> name [2]; vector<int> son[LEN]; int hash[M], ans , nodecnt=0, cnt[LEN], siz[LEN], vis[LEN]; struct node { node *fail; map<int,node*> next; int id; node(){id=0;fail=NULL;} }; struct ACAutomaton { node *root; void init() { root=new node(); root->fail=root; root->id=++nodecnt; } void insert(int len, int id) { node *p=root; for(int k = 1; k <= len; k++) { int x=in(); if(p->next[x]==NULL) { p->next[x]=new node(); p->next[x]->id=++nodecnt; son[p->id].push_back(x); } p=p->next[x]; } hash[id]=p->id; siz[p->id]++; } void build() { queue<node*> q; for(int j = 0, jj = son[root->id].size();j < jj; j++) { int i=son[root->id][j]; root->next[i]->fail=root; q.push(root->next[i]); } while(!q.empty()) { node *u=q.front(); q.pop(); for(int j = 0, jj = son[u->id].size(); j < jj; j++) { int i=son[u->id][j]; node *v=u->next[i], *t=u->fail; while(t!=root && !t->next[i]) { t=t->fail; } v->fail=t->next[i]?t->next[i]:root; q.push(v); } } } void solve(int x) { for(int k = 0; k < 2; k++) { node *p=root; for(int i = 0, ii = name[x][k].size(); i < ii; i++) { int c=name[x][k][i]; while(p!=root && !p->next[c])p=p->fail; if(p->next[c])p=p->next[c]; node *temp=p; for(;temp!=root;temp=temp->fail) { if(vis[temp->id]==x)continue; vis[temp->id]=x; ans[x]+=siz[temp->id]; cnt[temp->id]++; } } } } }AC; int main() { AC.init(); int n, m; scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) { for(int j = 0; j < 2; j++) { int k; scanf("%d",&k); for(int g = 1; g <= k; g++) name[i][j].push_back(in()); } } for(int i = 1; i <= m; i++) { int k=in(); AC.insert(k,i); } AC.build(); for(int i = 1; i <= n; i++) AC.solve(i); for(int i = 1; i <= m; i++) printf("%d\n",cnt[hash[i]]); for(int i = 1; i < n; i++) printf("%d ",ans[i]); printf("%d",ans ); }
相关文章推荐
- BZOJ 2754 SCOI2012 喵星球上的点名 fail树+set启发式合并
- 【bzoj2754】 SCOI2012—喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]
- bzoj 2754: [SCOI2012]喵星球上的点名
- BZOJ 2754([SCOI2012]喵星球上的点名-后缀数组统计序列集合中子序列出现次数)
- bzoj2754:[SCOI2012]喵星球上的点名(后缀自动机)
- BZOJ 2754: [SCOI2012]喵星球上的点名
- bzoj2754 [SCOI2012]喵星球上的点名
- bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】
- [bzoj2754] [SCOI2012]喵星球上的点名
- 【bzoj2754】[SCOI2012]喵星球上的点名 AC自动机优化的暴力
- BZOJ 2754: [SCOI2012]喵星球上的点名
- bzoj 2754: [SCOI2012]喵星球上的点名
- BZOJ_2754__[SCOI2012]_喵星球上的点名_(暴力+后缀数组)
- BZOJ2754 SCOI2012喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名 后缀数组
- BZOJ 2754: [SCOI2012]喵星球上的点名
- AC日记——[SCOI2012]喵星球上的点名 bzoj 2754
- BZOJ 2754: [SCOI2012]喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]