1. 程式人生 > >POJ1509 Glass Beads(最小表示法 字尾自動機)

POJ1509 Glass Beads(最小表示法 字尾自動機)

Time Limit: 3000MS Memory Limit: 10000K
Total Submissions: 4901 Accepted: 2765

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

Source

題目大意:對於給定的字串,輸出其最小表示法的第一個字元在第幾位

最小表示法:最小表示法又叫做最小迴圈表示。

你可以直觀的理解為對於一個字串,選一個位置把它劈開,把前一半接到後一半,形成一個新的字串,在這些新的字串中字典序最小的即為字串的最小表示。

最小表示法有專門的演算法(三指標法?https://www.cnblogs.com/XGHeaven/p/4009210.html)

但是它可以輕鬆的被SAM解決

我們先把SAM建出來,然後從根節點開始,每次走最小的轉移邊,走$|S|$次,所得的串即為最小表示

那麼第一個字母可用通過$len-|S|$找到

#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 40001;
int N;
char s[MAXN];
int fa[MAXN], len[MAXN], ch[MAXN][26], tot = 1, last = 1, root = 1; 
void insert(int x) {
    int now = ++tot, pre = last; last = now; len[now] = len[pre] + 1;
    for(; pre && !ch[pre][x]; pre = fa[pre]) 
        ch[pre][x] = now;
    if(!pre) fa[now] = root;
    else {
        int q = ch[pre][x];
        if(len[q] == len[pre] + 1) fa[now] = q;
        else {
            int nows = ++tot; len[nows] = len[pre] + 1;
            memcpy(ch[nows], ch[q], sizeof(ch[q]));
            fa[nows] = fa[q]; fa[q] = fa[now] = nows;
            for(; pre && ch[pre][x] == q; pre = fa[pre]) ch[pre][x] = nows;
        }
    }
}
int main() {
#ifdef WIN32
    freopen("a.in", "r", stdin);
#endif
    int QwQ;
    scanf("%d", &QwQ);
    while(QwQ--) {
        memset(fa, 0, sizeof(fa));
        memset(ch, 0, sizeof(ch));
        memset(len , 0, sizeof(len));
        tot = last = root = 1;
        scanf("%s", s + 1);
        N = strlen(s + 1);
        for(int i = 1; i <= N; i++) s[i + N] = s[i];
        N <<= 1;
        for(int i = 1; i <= N; i++) insert(s[i] - 'a');
        int now = root, tot = 0;
        for(; tot <= N / 2; tot++) {
            for(int i = 0; i <= 25; i++) 
                if(ch[now][i])
                    {now = ch[now][i]; putchar(i + 'a'); break;}    
        } 
        printf("%d\n", len[now] - N / 2);
    }
    return 0;
}

相關推薦

POJ1509 Glass Beads(表示 字尾自動機)

Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 4901 Accepted: 2765 Description Once upon a time there was a famous

【題解】POJ 1509 Glass Beads 表示模板

ostream 字母 void stream ldr fine clu 輸出 ring vjudge 題目大意TLDR 有$n$個首尾相接的字符串,每個字符串均由小寫字母構成,要求在環上找到一個斷點,使得斷開後所得的字符串字典序最小。 若有多處斷點斷開所得的字符串相同

Glass Beads -表示模板

Glass Beads #include<iostream> using namespace std; int t,n; string str; int getmin() { int i=0,j=1,k=0; while(i<

poj1509 表示

學習一下最小表示法……,部分內容與此題無關。 1.起始問題 :比較兩個字串是否迴圈同構        比如說abca和caab是迴圈同構的(abca和acba不是迴圈同構) 2.複雜度較高的演算法       例舉A串的所有迴圈同構串 和B串作比較:abca,bcaa,

hdu3374 kmp+表示

small clu 個數 ext 表示 abcde precision pre mes Give you a string with length N, you can generate N strings by left shifts. For example let c

hdu2609 表示

expr diff opened res str substr multiple min spa Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tel

51nod1282(表示&&枚舉)

表示 using pro int 情況 註意 str nbsp html 題目鏈接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1282 題意:中文題目誒~ 思路:指針不可轉,刻盤可轉,

hdu 2609 How many(表示)

strlen size pro lan hid none fine spl pri 題目鏈接:hdu 2609 How many 題意: 給你一些01串,a能通過循環到b的算一個種類,問有多少種串。 題解: 最小表示法板子題。 1 #include<bits/s

POJ1635 Subway tree systems ——(判斷樹的同構,樹的表示

systems scan color end cto 同構 while scanf urn   給兩棵有根樹,判斷是否同構。因為同構的樹的最小表示法唯一,那麽用最小表示法表示這兩棵樹,即可判斷同構。順便如果是無根樹的話可以通過選出重心以後套用之前的方法。   AC代碼如下:

hdu-2609 How many---表示模板+set判重

str AC lse ron max insert sin AS 最小表示法 題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=2609 題目大意: 有n個有01組成的字符串,每個字符串都代表一個項鏈,那麽該字符串就是一個環狀的

洛谷P1709 [USACO5.5]隱藏口令Hidden Password(表示)

else win32 換行 event 分享圖片 ios copy 得到 自動機 題目描述 有時候程序員有很奇怪的方法來隱藏他們的口令。Binny會選擇一個字符串S(由N個小寫字母組成,5<=N<=5,000,000),然後他把S順時針繞成一個圈,每次取一個做

2882: 工藝(表示

2882: 工藝 Time Limit: 10 Sec Memory Limit: 128 MB Description 小敏和小燕是一對好朋友。 他們正在玩一種神奇的遊戲,叫Minecraft。 他們現在要做一個由方塊構成的長條工藝品。但是方塊現在是亂的,而且由於機器的

ZOJ 1729 & ZOJ 2006(表示模板題)

輸出每個字串的最小字典序字串的下標! #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace

CH1807 Necklace【Hash】【字串】【表示

1807 Necklace 0x18「基本資料結構」練習 背景 有一天,袁☆同學綿了一條價值連城寶石項鍊,但是,一個嚴重的問題是,他竟然忘記了項鍊的主人是誰!在得知此事後,很多人向☆同學發來了很多郵件,都說項鍊是自己的,要求他歸還(顯然其中最多隻有一個人說了真話)。 ☆同學要求每個人都寫了一段關

表示模板(洛谷P1368 工藝)(表示

洛谷題目傳送門 最小表示是指一個字串通過迴圈位移變換(第一個移到最後一個)所能得到的字典序最小的字串。 因為是環狀的,所以肯定要先轉化為序列,把原串倍長。 設決策點為一個表示法的開頭。比較兩個決策點\(i,j\),找到它們的LCP(假設長度為\(k\))。 假設\(s_{i+k}>s_{j+k}

表示 詳解+模板+例題

最小表示法是求與某個字串迴圈同構的所有字串中,字典序最小的串是哪個。 比如說一個字串jdrakioi,它長為8,也就是說最多有八種迴圈同構的方法。 jdrakioi、drakioij、rakioijd、akioijdr、kioijdra、ioijdrak、oijdraki、ijdrakio。 這幾個串在

hdu3374 String Problem【表示】【exKMP】

output field can mis sep pan 題意 easy example String Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O

hdu 2609 How many (表示)

題目: Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell me How many kinds of necklaces

HDU2609——How many【表示,set去重】

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4190 &nbs

51nod 1282 時鐘 (雜湊、字串的表示

題目 題解 要判斷時鐘是否相同,只需將時鐘的指標排序後求出M個距離,然後看距離陣列是否是迴圈同構即可。 迴圈同構: abcd的迴圈同構有:abcd、bcda、cdba、dabc。 要判斷是否迴圈同構,可以求出距離陣列的最小表示。然後對這個最小表示陣