题意:
给一个字符串S,每次可以将它的第一个字符移到最后面,求这样能得到的字典序最小的字符串。输出开始下标
Sample Input
4 helloworld amandamanda dontcallmebfu aaabaaaSample 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 ",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 }