您的位置:首页 > 其它

hdu4436 SAM_多串匹配

2014-06-22 12:47 381 查看
题目链接:Click here

将多个串合并到一起,中间用一个符号分割就好了。 如果选用的是10来分割,  则最后计算的时候只用计算节点 0至于9就可以了。

有一点需要注意。 对于前导0 , 可以在读入的时候就处理掉,不添加这个节点,也可以在最后拓扑排序的时候处理掉。

如果不处理这个前导0, 则会多计算一部分的后缀,导致结果变大。

cnt是记录这个重复串出现了几次。

0 0拓扑排序从根节点开始进行遍历下去。

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;

const int MAX_NODES = 411111;
const int N = 221111;
struct node{
struct node *ch[12];
struct node *f;
int mx;
int sum,cnt;
void init(){
memset(ch,0,sizeof(ch));
f = 0; cnt = sum = 0;
}
}*root,*cnt,*tail,pool[MAX_NODES];

int n;
char s
;
void init(){
root = cnt = tail = pool ;
root ->init();
cnt++;
}
void add(int c,int len){
node *p = tail, *np = cnt++;
np->init();
for( ; p && !p->ch[c] ; p = p->f) p->ch[c] = np;
np->mx = len;
tail = np;
if(!p) np->f = root;
else
if( p->ch[c]->mx == p->mx+1) np->f = p->ch[c];
else{
node *q = p->ch[c], *r = cnt++;
*r = *q;
r->mx = p->mx+1;
q->f = np->f = r;
for( ; p && p->ch[c] == q ; p = p->f) p->ch[c] = r;
}
}
int rc
, top
;
int so
;
bool cmp(int a,int b){
return pool[a].mx < pool[b].mx;
}
const int MOD = 2012;
int main(){
while(scanf("%d",&n)!=EOF){
init();
int pre = 0;
for(int i = 0;i < n;i++){
scanf("%s",s);
for(int j = 0; s[j] ;j++){
add(s[j]-'0',++pre);
}
if(i+1<n)
add(10,++pre);
}
memset(rc,0,sizeof(rc));
int tot = cnt - root;

//for(int i = 0;i < tot;i++){
//	printf("pool[%d]=%d\n",i,pool[i].mx);
//}
for(int i = 0;i < tot; i++)
rc[pool[i].mx]++;
for(int i = 1;i < tot; i++)
rc[i] += rc[i-1];
for(int i = tot-1;i > 0;i--)
top[--rc[pool[i].mx]] = i;

//for(int i = 0;i < tot;i++)
//	so[i] = i;
//sort(so,so+tot,cmp);
int ans = 0;
pool[0].cnt = 1;
for(int i = 0;i < tot;i++){
node * q = &pool[top[i]];
//printf("top[%d]=%d\n",i,top[i]);
//node *q = &pool[so[i]];
if(i > 0 && !q->cnt) continue;
ans = (ans + q->sum ) % MOD;
//printf("q->sum = %d\n",q->sum);
//printf("ans=%d\n",ans);
for(int j = 0;j < 10;j++){
if(i==0 && j == 0)continue; // 去掉前导0
if(q->ch[j]){
q->ch[j]->sum = (q->ch[j]->sum + q->sum*10 + q->cnt * j) % MOD;
q->ch[j]->cnt += q->cnt;

//printf("q->ch[%d]->cnt=%d\n",j,q->ch[j]->cnt);
//printf("q->ch[%d]->sum=%d\n",j,q->ch[j]->sum);
}
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HDU ACM SAM