POJ1509 GlassBeads

版权声明:随意转载,愿意的话提一句作者就好了 https://blog.csdn.net/stone41123/article/details/84061320

Link

Difficulty

算法难度8,思维难度5,代码难度6

Description

给定一个串,你可以把开头字符放到结尾,这个操作可以执行任意次

求使得最终串字典序最小的起点在哪个位置

多组询问,单组长度不超过 10000 10000

Solution

把字符串复制一遍接在后面,然后建SAM

从根节点开始走,每次走可以走的最小边,走n步到达的点就是答案

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
inline int read(){
	int x=0,f=1;char ch=' ';
	while(ch<'0' || ch>'9'){if(ch=='0')f=-1;ch=getchar();}
	while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return f==1?x:-x;
}
const int N=1e5+5;
namespace SAM{
	int last,cnt;
	int ch[N][26],l[N],fa[N];
	inline void insert(int c){
		int p=last,np=++cnt;last=np;l[np]=l[p]+1;
		for(;p && !ch[p][c];p=fa[p])ch[p][c]=np;
		if(!p)fa[np]=1;
		else{
			int q=ch[p][c];
			if(l[q]==l[p]+1)fa[np]=q;
			else{
				int nq=++cnt;l[nq]=l[p]+1;
				memcpy(ch[nq],ch[q],sizeof ch[nq]);
				fa[nq]=fa[q];fa[q]=fa[np]=nq;
				for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
			}
		}
	}
	inline void init(){
		for(int i=1;i<=cnt;++i){
			l[i]=fa[i]=0;
			memset(ch[i],0,sizeof ch[i]);
		}
		last=cnt=1;
	}
};
int T,n;
char ch[N];
int main(){
	T=read();
	while(T--){
		memset(ch,0,sizeof ch);
		SAM::init();
		scanf("%s",ch+1);
		n=strlen(ch+1);
		for(int i=1;i<=n;++i)SAM::insert(ch[i]-'a');
		for(int i=1;i<=n;++i)SAM::insert(ch[i]-'a');
		int now=1;
		for(int i=1;i<=n;++i)
			for(int k=0;k<26;++k)
				if(SAM::ch[now][k]){
					now=SAM::ch[now][k];
					break;
				}
		printf("%d\n",SAM::l[now]-n+1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/stone41123/article/details/84061320