题意:
给你一个字符串的环,求从那个位置起字符串的字典序最小。
题解:
最小表示法。

1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <algorithm> 6 7 #define N 20200 8 //求最小循环同构串起点 9 using namespace std; 10 11 char str[N]; 12 int len; 13 14 inline int go() 15 { 16 scanf("%s",str); 17 len=strlen(str); 18 int i=0,j=1,k=0,pi,pj; 19 while(1) 20 { 21 if(k==len) return i; 22 if(i==j) j++;//!! 23 pi=(i+k)%len; 24 pj=(j+k)%len; 25 if(str[pi]>str[pj]) i+=k+1,k=0; 26 else if(str[pj]>str[pi]) j+=k+1,k=0; 27 else k++; 28 } 29 } 30 31 int main() 32 { 33 int cas; scanf("%d",&cas); 34 while(cas--) printf("%d\n",go()+1); 35 return 0; 36 }
其实更容易想到的是后缀自动机。。
我会告诉你这个是后缀自动机的例题?
将原串扩充成原来的二倍,构建后缀自动机,然后将原串在后缀自动机上匹配,即可。
需要在后缀自动机上每个节点搞一个s值表示这个节点所表示的串在扩充后的串中的位置。

1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cstdio> 5 #include <algorithm> 6 7 #define N 20010 8 9 using namespace std; 10 11 struct SAM 12 { 13 SAM *son[26],*f; 14 int l,s; 15 }sam[N],*head,*last; 16 17 char str[N]; 18 int cnt,len; 19 20 inline void add(int x) 21 { 22 SAM *p=&sam[++cnt],*jp=last; 23 p->l=last->l+1; p->s=p->l; 24 last=p; 25 for(;jp&&!jp->son[x];jp=jp->f) jp->son[x]=p; 26 if(!jp) p->f=head; 27 else if(jp->l+1==jp->son[x]->l) p->f=jp->son[x]; 28 else 29 { 30 SAM *r=&sam[++cnt],*q=jp->son[x]; 31 *r=*q; r->l=jp->l+1; r->s=p->l; 32 q->f=p->f=r; 33 for(;jp&&jp->son[x]==q;jp=jp->f) jp->son[x]=r; 34 } 35 } 36 37 inline void read() 38 { 39 scanf("%s",str); 40 len=strlen(str); 41 memset(&sam,0,sizeof sam); 42 head=last=&sam[cnt=0]; 43 for(int i=0;i<len;i++) str[i]-='a',str[i+len]=str[i]; 44 for(int i=0;i<(len<<1);i++) add(str[i]); 45 } 46 47 inline void go() 48 { 49 last=head; 50 for(int i=0;i<len;i++) 51 for(int j=0;j<26;j++) 52 if(last->son[j]) {last=last->son[j];break;} 53 printf("%d\n",last->s-len+1); 54 } 55 56 int main() 57 { 58 int cas; scanf("%d",&cas); 59 while(cas--) read(),go(); 60 return 0; 61 }