POJ 1509 Glass Beads 后缀自动机

题目大意:给出一个环形的字符串,问从哪里开始是的这个字符串的字典序最小。

思路:最小表示法和后缀自动机的裸题,不过我是为了学后缀自动机才写的这个题,就没有去学最小表示法。

做法很简单,先建立一个后缀自动机,然后从根开始沿tranc指针从a->z走len次到达的点就是字典序最小的字符串的结尾点,求起始点只要减一下长度再+1即可。

对于后缀自动机的理解:http://wyfcyx.is-programmer.com/posts/76107.html

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 10010
using namespace std;

struct Complex{
	Complex *tranc[26],*father;
	short len;
}mempool[MAX << 2],*C = mempool,none,*nil = &none,*root,*last;
Complex *NewComplex(int _)
{
	C->len = _;
	fill(C->tranc,C->tranc + 26,nil);
	C->father = nil;
	return C++;
}

int T;
char s[MAX];

inline void Initialize()
{
	C = mempool;
	root = last = NewComplex(0);
}

inline void Add(int c)
{
	Complex *np = NewComplex(last->len + 1),*p = last;
	for(; p != nil && p->tranc[c] == nil; p = p->father)
		p->tranc[c] = np;
	if(p == nil)	np->father = root;
	else {
		Complex *q = p->tranc[c];
		if(q->len == p->len + 1)	np->father = q;
		else {
			Complex *nq = NewComplex(p->len + 1);
			nq->father = q->father;
			q->father = np->father = nq;
			memcpy(nq->tranc,q->tranc,sizeof(q->tranc));
			for(; p != nil && p->tranc[c] == q; p = p->father)
				p->tranc[c] = nq;
		}
	}
	last = np;
}

int main()
{
	for(cin >> T; T--;) {
		Initialize();
		scanf("%s",s);
		int length = strlen(s);
		for(int i = 0; i < length; ++i)
			Add(s[i] - 'a');
		for(int i = 0; i < length; ++i)
			Add(s[i] - 'a');
		Complex *now = root;
		for(int i = 0; i < length; ++i)
			for(int j = 0; j < 26; ++j)
				if(now->tranc[j] != nil) {
					now = now->tranc[j];
					break;
				}
		printf("%d\n",now->len - length + 1);
	}
}

时间: 2024-08-25 17:49:54

POJ 1509 Glass Beads 后缀自动机的相关文章

POJ 1509 Glass Beads 后缀自动机 模板 字符串的最小表示

http://poj.org/problem?id=1509 后缀自动机其实就是一个压缩储存空间时间(对节点重复利用)的储存所有一个字符串所有子串的trie树,如果想不起来长什么样子可以百度一下找个图回忆,从0开始到任意一个点的串都是字符串的子串. 有一些很好用的性质. 字符串的最小表示就是把一个字符串首尾相连再从任意一个地方断开产生的字典序最小的字符串,这个题是求最小表示的开头字母在原字符串中的下标(从1开始). 具体看实现吧,没什么可以解释的地方. 1 #include<iostream>

[最小表示] poj 1509 Glass Beads

题目链接: http://poj.org/problem?id=1509 Glass Beads Time Limit: 3000MS   Memory Limit: 10000K Total Submissions: 2311   Accepted: 1343 Description Once upon a time there was a famous actress. As you may expect, she played mostly Antique Comedies most of

●POJ 1509 Glass Beads

题链: http://poj.org/problem?id=1509 题解: 给出一个字符串,有一个操作:把首字符放到末尾,形成新的串.求任意次操作后,字典序最小的串的首字母在原串中的位置.(这就是最小表示法?哈) 把原串翻倍,建立后缀自动机.然后在自动机上从起点往当前节点的较小的字母上跑len步即可.代码: #include<cstdio> #include<cstring> #include<iostream> #define MAXN 40050 #define

poj 1509 Glass Beads

题意:给你一个长度为n的字符串环,以位置i开始的顺时针长度为n的环构成的字符串有n个,问其中最小字典序的开始位置,有多种解时,输出起始位置最小的. 分析: 首先可以直接拼接两个长度为n的字符串,设原串为S[0],S[1]...S[n-1]则拼接后就是S'=S[0],S[1],...S[n-1],S[0],S[1],...S[n-1]. 那么问题中的n个长度为n的字符串中的任意一个,一定存在S'的某个后缀字符串的前缀与其相等. 我们现在要找最小字典序,则可以直接先求S'的后缀数组SA,然后: 1.

PKU 1509 Glass Beads (最小表示法)

题意:有一个环形字符串,让你找一个位置切一刀使得字符串字母序最小,输出这个位置. 思路:可以看成两个字符串比较,一个是从下标0开始(0~n-1),一个从下标1开始(1~n-1,0). 然后两个指针i=0,j=1.从s[i]和s[j]开始比较第k个字符是否相同,当k==len时,返回i,j中的最小值.当s[i+k]和s[j+k]不相同时,若s[i+k]>s[j+k]则可见从s[i+1]到s[i+k]都不会是最小字典序的起始位置,所以i=i+k+1.当s[i+k]<s[j+k]时同理.若移动后i=

POJ 1509 Glass Beads---最小表示法

题意: T组数据,每组数据给出一个字符串,求这个字符串的最小表示发(只要求输出起始位置坐标) SAM入门题(检测板子是否正确). 将字符串S加倍丢进SAM中,然后走字符串长度次,每次贪心的沿最小的边走,然后答案就是:sam.e[po].len-len+1 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib&

POJ1509 Glass Beads 【后缀自动机】

题目大意 找一个环串的起点,使得从其开始遍历字典序最小 题解 建立后缀自动机,从根开始走length步,走到的点就是这个最小串的结尾,其step即表示它在串中的位置 step - n + 1即为开始位置 #include<iostream> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long int #define

【POJ1509】Glass Beads 【后缀自动机】

题意 给出一个字符串,求它的最小表示法. 分析 这个题当然可以用最小表示法做啦!但是我是为了学后缀自动机鸭! 我们把这个字符串长度乘二,然后建SAM,然后在SAM上每次跑最小的那个字母,找出长度为n的时候就停下.如果停下的那个状态时u,那么ans=st[u].len-n+1 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #incl

poj 2774 最长公共子串--字符串hash或者后缀数组或者后缀自动机

http://poj.org/problem?id=2774 想用后缀数组的看这里:http://blog.csdn.net/u011026968/article/details/22801015 本文主要讲下怎么hash去找 开始的时候写的是O(n^2 logn)算法 果断超时...虽然也用了二分的,, 代码如下: //hash+二分 #include <cstdio> #include <cstring> #include <algorithm> #include