HDU 4641 SAM

56 篇文章 0 订阅
4 篇文章 0 订阅


动态在尾部加入字符,统计相同字符串出现次数 >= k 得字符串有多少个。

0 0很显然用 SAM来做。 每次当这个节点出现了k次之后,就增加了  p->cnt -  p->f-cnt 得数目得子串

用cout竟然超时了。0 0.。。 哎。。换成printf才过掉。。坑于cout


#include <cstdio>
#include <cstdlib>
#include <iostream>

using namespace std;
const int MAX_NODES = 1006666;
const int N = 755555;
struct node{
	struct node* ch[26];
	struct node* f;
	int mx,cnt;
	void init(){
		memset(ch,0,sizeof(ch));
		f = 0; mx = 0 ; cnt = 0; 
	}
	int calc(){	
		return mx-f->mx;
	}
}*root,*cur,*tail,pool[MAX_NODES];

bool vis[MAX_NODES];
void add(int c){
	node *p = tail, *np = cur++;np->init(); 
	for( ; p && !p->ch[c] ;p=p->f) p->ch[c] = np;
	np->mx = tail->mx+1; 
	tail = np ;
	if(!p) np->f = root;
	else 
		if(p->mx+1 == p->ch[c]->mx) np->f = p->ch[c];
		else{
			node * q = p->ch[c] , *r = cur++;  
			*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;
		}
}
char s[N];
int len;
long long ans;
int n,m,k;
void cc(){
	node *p = tail;
	for( ; p != root && !vis[p-root]; p = p->f){
		if(p->cnt>=k) break; // 判断父亲节点是否已经计算过了。。
		p->cnt++;
		if(p->cnt>=k){
			ans += p->calc();
		}
	}
}
void suffix_auto_init(){
	int i;
	ans = 0;
	root = cur = tail = pool; cur++; root->init();
	for(i = 0; s[i] ;i++){
		add(s[i]-'a');
		cc();
	}
	len = i;
}

char ts[10];
int main(){
	int q,vq;
	while(scanf("%d %d %d",&n,&m,&k)!=EOF){
		scanf("%s",s);
		suffix_auto_init();
		while(m--){
			scanf("%d",&vq);
			if(vq==2){
				printf("%I64d\n",ans);
			}else{
				scanf("%s",ts);
				add(ts[0]-'a');
				cc();
			}
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值