Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 841 Accepted Submission(s): 297
使用SAM进行多串建立。
然后拓扑排序,
之后累加计数就可以了。
注意前导0的要去掉。
/* *********************************************** Author :kuangbin Created Time :2013-10-11 17:50:31 File Name :E:\2013ACM\专题强化训练\区域赛\2012天津\F.cpp ************************************************ */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h> #include <stdlib.h> #include <time.h> using namespace std; const int MOD = 2012; const int CHAR = 10; const int MAXN = 100010; struct SAM_Node { SAM_Node *fa, *next[CHAR]; int len; int id,pos; int cnt; int sum; SAM_Node(){} SAM_Node(int _len) { fa = 0; len = _len; memset(next,0,sizeof(next)); cnt = sum = 0; } }; SAM_Node SAM_node[MAXN*2], *SAM_root, *SAM_last; int SAM_size; SAM_Node *newSAM_Node(int len) { SAM_node[SAM_size] = SAM_Node(len); SAM_node[SAM_size].id = SAM_size; return &SAM_node[SAM_size++]; } SAM_Node *newSAM_Node(SAM_Node *p) { SAM_node[SAM_size] = *p; SAM_node[SAM_size].id = SAM_size; SAM_node[SAM_size].cnt = SAM_node[SAM_size].sum = 0; return &SAM_node[SAM_size++]; } void SAM_init() { SAM_size = 0; SAM_root = SAM_last = newSAM_Node(0); SAM_node[0].pos = 0; } void SAM_add(int x,int len) { SAM_Node *p = SAM_last, *np = newSAM_Node(p->len+1); np->pos = len; SAM_last = np; for(;p && !p->next[x];p = p->fa) p->next[x] = np; if(!p) { np->fa = SAM_root; return; } SAM_Node *q = p->next[x]; if(q->len == p->len + 1) { np->fa = q; return; } SAM_Node *nq = newSAM_Node(q); nq->len = p->len + 1; q->fa = nq; np->fa = nq; for(;p && p->next[x] == q;p = p->fa) p->next[x] = nq; } //多串的建立,注意SAM_init()的调用 void SAM_build(char *s) { int len = strlen(s); SAM_last = SAM_root; for(int i = 0;i < len;i++) { if( !SAM_last->next[s[i] - '0'] || !(SAM_last->next[s[i] - '0']->len == i+1) ) SAM_add(s[i] - '0',i+1); else SAM_last = SAM_last->next[s[i] - '0']; } } char str[MAXN]; int topocnt[MAXN]; SAM_Node *topsam[MAXN*2]; int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; while(scanf("%d",&n) == 1) { SAM_init(); for(int i = 0;i < n;i++) { scanf("%s",str); SAM_build(str); } //continue; memset(topocnt,0,sizeof(topocnt)); for(int i = 0;i < SAM_size;i++) topocnt[SAM_node[i].len]++; for(int i = 1;i < MAXN;i++) topocnt[i] += topocnt[i-1]; for(int i = 0;i < SAM_size;i++) topsam[--topocnt[SAM_node[i].len]] = &SAM_node[i]; int ans = 0; SAM_root->cnt = 1; for(int i = 0;i < SAM_size;i++) { SAM_Node *tmp = topsam[i]; for(int j = 0;j < 10;j++) { if(i == 0 && j == 0)continue; if(tmp->next[j]) { SAM_Node *q = tmp->next[j]; q->cnt = (q->cnt + tmp->cnt)%MOD; q->sum = (q->sum + tmp->sum*10+tmp->cnt*j)%MOD; } } ans = (ans + tmp->sum)%MOD; } printf("%d\n",ans); } return 0; }