Poj 1509

Glass Beads

Time Limit: 3000MS   Memory Limit: 10000K
Total Submissions: 2827   Accepted: 1634

Description

Once upon a time there was a famous actress. As you may expect, she played mostly Antique Comedies most of all. All the people loved her. But she was not interested in the crowds. Her big hobby were beads of any kind. Many bead makers were working for her and they manufactured new necklaces and bracelets every day. One day she called her main Inspector of Bead Makers (IBM) and told him she wanted a very long and special necklace.

The necklace should be made of glass beads of different sizes
connected to each other but without any thread running through the
beads, so that means the beads can be disconnected at any point. The
actress chose the succession of beads she wants to have and the IBM
promised to make the necklace. But then he realized a problem. The joint
between two neighbouring beads is not very robust so it is possible
that the necklace will get torn by its own weight. The situation becomes
even worse when the necklace is disjoined. Moreover, the point of
disconnection is very important. If there are small beads at the
beginning, the possibility of tearing is much higher than if there were
large beads. IBM wants to test the robustness of a necklace so he needs a
program that will be able to determine the worst possible point of
disjoining the beads.

The description of the necklace is a string A = a1a2 ... am
specifying sizes of the particular beads, where the last character am is
considered to precede character a1 in circular fashion.

The disjoint point i is said to be worse than the disjoint point j
if and only if the string aiai+1 ... ana1 ... ai-1 is lexicografically
smaller than the string ajaj+1 ... ana1 ... aj-1. String a1a2 ... an is
lexicografically smaller than the string b1b2 ... bn if and only if
there exists an integer i, i <= n, so that aj=bj, for each j, 1 <=
j < i and ai < bi

Input

The
input consists of N cases. The first line of the input contains only
positive integer N. Then follow the cases. Each case consists of exactly
one line containing necklace description. Maximal length of each
description is 10000 characters. Each bead is represented by a
lower-case character of the english alphabet (a--z), where a < b
... z.

Output

For
each case, print exactly one line containing only one integer -- number
of the bead which is the first at the worst possible disjoining, i.e.\
such i, that the string A[i] is lexicographically smallest among all the
n possible disjoinings of a necklace. If there are more than one
solution, print the one with the lowest i.

Sample Input

4
helloworld
amandamanda
dontcallmebfu
aaabaaa

Sample Output

10
11
6
5

大意:给出多组数据,每组数据包含一个字符串,求出这个字符串的同构串中字典序最小的串,输出开始的位置.

分析:后缀自动机的简单应用:

后缀自动机的性质就是从初始态走到任意一个节点都是当前字符串的字串.证明:后缀自动机能够接受当前的串的所有的后缀.在某个时刻,查询的字符串就是整个字符串某个前缀的后缀.所以能够接受.根据这个性质

把两个串接在一起,然后就直接在上面依着最小字典序的边贪心地跑,最后跑到一个终止节点.如何计算起始位置呢?这个串能够接受的最长的串长,也就是这个点的step.就是从字符串开始到这个点在字符串中的长度.(它曾经是一个结束节点last)

所以我们只要用它减掉原串长就ok了.

代码比较简单.

 1 #include<cstdlib>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 using namespace std;
 7 const int maxn = (int)1e5, sigma = 26;
 8 struct Sam{
 9     int ch[maxn][sigma],par[maxn];
10     int stp[maxn];
11     int sz,last;
12     void init(){
13         memset(ch,0,sizeof(ch));
14         memset(par,0,sizeof(par));
15         memset(stp,0,sizeof(stp));
16         sz = last = 1;
17     }
18     void extend(int c){
19         stp[++sz] = stp[last] + 1;
20         int p = last, np = sz;
21         for(; !ch[p][c]; p = par[p]) ch[p][c] = np;
22         if(p == 0) par[np] = 1;
23         else{
24             int q = ch[p][c];
25             if(stp[q] != stp[p] + 1){
26                 stp[++sz] = stp[p] + 1;
27                 int nq = sz;
28                 memcpy(ch[nq],ch[q],sizeof(ch[q]));
29                 par[nq] = par[q];
30                 par[q] = par[np] = nq;
31                 for(; ch[p][c] == q; p = par[p]) ch[p][c] = nq;
32             }
33             else par[np] = q;
34         }
35         last = np;
36     }
37     void build(string &s){
38         int i;
39         init();
40         for(i = 0; i < s.size(); ++i) extend(s[i] - ‘a‘);
41     }
42     void vis(int len){
43         int x = 1,i,j;
44         for(i = 0; i < len; ++i)
45             for(j = 0; j < sigma; ++j)
46                 if(ch[x][j]){ x = ch[x][j]; break; }
47         cout << stp[x] - len + 1 << endl;
48     }
49 }sam;
50 string s;
51 int main()
52 {
53     freopen("bead.in","r",stdin);
54     freopen("bead.out","w",stdout);
55     ios::sync_with_stdio(false);
56     int n,i;
57     cin >> n;
58     for(i = 1; i <= n; ++i){
59         cin >> s;
60         s = s + s;
61         sam.build(s);
62         sam.vis(s.size() / 2);
63     }
64     return 0;
65 }

时间: 2024-10-12 16:20:03

Poj 1509的相关文章

[最小表示] 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 后缀自动机 模板 字符串的最小表示

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

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&

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.

POJ 1509 后缀数组

点击打开链接 题意:给个串问最小的后缀,但是这个串是个环 思路:是个环也好处理,那么就将串复制一遍加到后面就行了,然后求出后缀数组和高度数组,刚开始我写的是就求出后缀数组sa,然后从排名第1开始找,比如找到了I,排名为I的从第sa[I]开始,那么如果这个值小于输入串的长度,直接输出就行,提交WA,看了看讨论,有这样的数组,aaaa那么应该输出1,而那个程序输出4,然后想到用高度数组,刚开始找到4的位置,然后找下一个排名的高度数组,如果lcp的值大于串的长度,那么更新结果,以此类推直到lcp的值不

POJ 1509 Glass Beads 后缀自动机

题目大意:给出一个环形的字符串,问从哪里开始是的这个字符串的字典序最小. 思路:最小表示法和后缀自动机的裸题,不过我是为了学后缀自动机才写的这个题,就没有去学最小表示法. 做法很简单,先建立一个后缀自动机,然后从根开始沿tranc指针从a->z走len次到达的点就是字典序最小的字符串的结尾点,求起始点只要减一下长度再+1即可. 对于后缀自动机的理解:http://wyfcyx.is-programmer.com/posts/76107.html CODE: #include <cstdio&g

POJ 1509 循环同构的最小表示法

题目大意: 给定一个字符串,可以把一段尾部接到头部,这样找到一个最小的字符串 方案一: 利用循环同构中找最小表示的方法来解决 论文参考http://wenku.baidu.com/view/438cad13a2161479171128b6.html 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 #define N 10005 7 char

『后缀自动机入门 SuffixAutomaton』

本文的图片材料多数来自\(\mathrm{hihocoder}\)中详尽的\(SAM\)介绍,文字总结为原创内容. 确定性有限状态自动机 DFA 首先我们要定义确定性有限状态自动机\(\mathrm{DFA}\),一个有限状态自动机可以用一个五元组\((\mathrm{S},\Sigma,\mathrm{st},\mathrm{end},\delta)\)表示,他们的含义如下: \(1.\) \(\mathrm{S}\) 代表自动机的状态集 \(2.\) \(\Sigma\) 代表字符集,也称字