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>
 6 #include<cmath>
 7 #include<cstring>
 8 using namespace std;
 9 #define maxn 10010
10 #define llg long long
11 #define SIZE 26
12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
13 llg n,m,T;
14
15 char s[maxn];
16
17 struct SAM
18 {
19     struct
20     {
21         llg len,f/*parent边*/,ch[SIZE];
22         void init()
23         {
24             len=0,f=-1;
25             memset(ch,0xff,sizeof(ch));
26         }
27     }e[maxn<<1];
28     llg idx,last;
29
30     void init() {idx=last=0; e[idx++].init();}
31
32     int newnode() {e[idx].init(); return idx++;}
33
34     void add(llg c)
35     {
36         int end=newnode(),tmp=last;
37         e[end].len=e[last].len+1;
38         for (;tmp!=-1 && e[tmp].ch[c]==-1;tmp=e[tmp].f){e[tmp].ch[c]=end;}//跳parent tree的边,找到第一个具有c出边的点并停下,对于没有的点连出一条边权是c的边指向当前点(end)。
39         if (tmp==-1) e[end].f=0;//如果没有任何一个点有权值为c的出边,则说明了相应字符c是第一次出现在自动机中。
40         else
41         {
42             llg nxt=e[tmp].ch[c];
43             if (e[tmp].len+1==e[nxt].len) e[end].f=nxt;//如果找到的第一个具有出边c的点的出边c左指向点的len=lastlen+1,则直接把新建点的parent边连向nxt点。
44             else
45             {
46                 llg np=newnode();
47                 e[np]=e[nxt];
48                 e[np].len=e[tmp].len+1;//新建点np
49                 e[nxt].f=e[end].f=np;
50                 for (;tmp!=-1 && e[tmp].ch[c]==nxt;tmp=e[tmp].f) {e[tmp].ch[c]=np;}//沿parent边往祖先走把所有原本连向nxt的带边权c的边改为连向np
51             }//如果不满足MAX(s)+1=MAX(s[tmp][c])则新建点
52         }
53         last=end;
54     }
55 }sam;
56
57 int main()
58 {
59     yyj("SAM");
60     cin>>T;
61     while (T--)
62     {
63         sam.init();
64         scanf("%s",s);
65         llg len=strlen(s);
66         for (llg i=0;i<len;i++) sam.add(s[i]-‘a‘);
67         for (llg i=0;i<len;i++) sam.add(s[i]-‘a‘);
68         llg po=0;
69         for (llg i=0;i<len;i++)
70             for (llg j=0;j<26;j++)
71                 if (sam.e[po].ch[j]!=-1)
72                 {
73                     po=sam.e[po].ch[j];
74                     break;
75                 }
76         printf("%lld\n",sam.e[po].len-len+1);
77     }
78     return 0;
79 }
时间: 2024-10-13 17:31:03

POJ 1509 Glass Beads---最小表示法的相关文章

[最小表示] 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 后缀自动机

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

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

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

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 1635 树的最小表示法/HASH

题目链接:http://poj.org/problem?id=1635 题意:给定两个由01组成的串,0代表远离根,1代表接近根.相当于每个串对应一个有根的树.然后让你判断2个串构成的树是否是同构的. 思路:首先根据01串构造出树,然后求树的最小表示法判断同构. 详情参照:https://www.byvoid.com/blog/directed-tree-bracket-sequence/ #define _CRT_SECURE_NO_DEPRECATE #include<iostream>

POJ 1635 树的最小表示法

题目大意: 用一堆01字符串表示在树上走动的路径,0表示往前走,1表示往回走,问两种路径方式下形成的树是不是相同的树 我们可以利用递归的方法用hash字符串表示每一棵子树,然后将所有子树按照字典序排序,来判断这个hash字符串是否相同 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <string> 5 #include <algorithm> 6

SPOJ-BEADS UVA719 UVALive5545 POJ1509 ZOJ2006 Glass Beads【字符串环的最小】

Glass Beads Time Limit: 3000MS Memory Limit: 10000K Total Submissions: 5254 Accepted: 2943 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 w