poj1509_SAM_简单题。。

4 篇文章 0 订阅
1 篇文章 0 订阅


题目: click here

找一个字典序最小的循环链的起始点。

SAM化后,从根节点每次选择子节点最小的,走n步就好了。。


#include <cstdio>
#include <cstdlib>
#include <cstring>

const int MAX_NODES = 3555555;
const int N = 1111111;
struct node{
	struct node *ch[26];
	struct node *f;
	int mx;
	void init(){
		memset(ch,0,sizeof(ch));
		f = 0;
	}
}*root,*cnt,*tail,pool[MAX_NODES];
char s[N],ts[N];
int n;
void insert(int c,int len){
	node *p = tail, *np = cnt++;
	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; 
		}
}
void init_suffix_auto(char s[]){
	int len = 0;
	tail = cnt = root = pool; cnt++ , root->init();
	for(int i = 0;i < (n<<1) ;i++)
		pool[i].init();
	for( ; s[len] ; len++){
		insert(s[len] - 'a', len+1);
	}
}
int rank[N];
int dfs(int u,int step){
	node * q = &pool[u];
	if(step == n){
		return q->mx;
	}
	for(int i = 0;i < 26;i++){
		if(q->ch[i]){
			return dfs(q->ch[i]-root,step+1);
		}
	}
	return 0;
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		scanf("%s",ts);
		n = strlen(ts);
		strcpy(s,ts);
		strcpy(s+n,ts);
		init_suffix_auto(s);
		int ans = dfs(0,0)-n;
		printf("%d\n",ans+1);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值