POJ1509,ZOJ2006,ZOJ1729 Glass Beads

题意:

给一个字符串S,每次可以将它的第一个字符移到最后面,求这样能得到的字典序最小的字符串。输出开始下标

Sample Input
4
helloworld
amandamanda
dontcallmebfu
aaabaaa
Sample Output
10
11
6
5
  • 因为sam里的任意条路径都是S的一个子串,所以可以把原串复制一遍(模拟移动字符的操作),然后在后来长为2L的串上走n步,每次走都从字典序最小的边转移。
  • 注意数组大小
  • 注意走的步数够不够n步
  • (貌似该用最小表示法,不管啦反正sam能过)
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<map>
 5 using namespace std;
 6 const int N=40005;
 7 int c[N][27];
 8 int n,T,f[N],pre,cnt,l[N];
 9 char s[N];
10 int ans;
11 inline void clr(){
12     pre=cnt=1;ans=0;memset(f,0,sizeof(f));memset(l,0,sizeof(l));memset(c,0,sizeof(c));
13 }
14 inline void ins(int x){
15     int p=pre,np=++cnt;pre=np;
16     l[np]=l[p]+1;
17     for(;p&&!c[p][x];p=f[p])c[p][x]=np;
18     if(!p)f[np]=1;
19     else{
20         int q=c[p][x];
21         if(l[q]==l[p]+1)f[np]=q;
22         else{
23             int nq=++cnt;
24             l[nq]=l[p]+1;
25             memcpy(c[nq],c[q],sizeof(c[q]));
26             f[nq]=f[q];f[q]=f[np]=nq;
27             for(;c[p][x]==q;p=f[p])c[p][x]=nq;
28         }
29     }
30 }
31 inline void sol(){
32     int now=1,nn=n;bool yigai=0;
33     while(nn--){
34         for(int i=0;i<26;++i){
35             if(c[now][i]){
36                 char w=i+'a';//printf("%c",w);
37                 now=c[now][i];yigai=1;break;
38             }
39         }
40         if(!yigai){
41             ++nn;
42         }
43     }
44     printf("%d\n",l[now]-n+1);
45 }
46 int main(){
47     scanf("%d",&T);
48     while(T--){
49         clr();
50         scanf("%s",s);
51         n=strlen(s);
52         for(int i=0;i<n;++i)ins(s[i]-'a');
53         for(int i=n;i<n+n;++i)ins(s[i-n]-'a');
54         sol();
55     
56     }
57     return 0;
58 }

 

 

posted @ 2018-03-21 00:36  better?  阅读(133)  评论(0编辑  收藏  举报