您的位置:首页 > 其它

HDU 4436 str2int (后缀自动机SAM,多串建立)

2016-10-11 21:34 507 查看
使用SAM进行多串建立。
 
然后拓扑排序,
之后累加计数就可以了。
注意前导0的要去掉。
#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: