Http://poj.org/problem? Id = 1509
It is the position of the starting character in the minimum notation of a string. If there are multiple characters, the minimum position is obtained.
Idea: This question is self-idle with the suffix of the automatic machine. It is a little tricky. This question has other more streamlined algorithms, and the time complexity is O (n ), but here Sam can be used to have a clearer understanding of Sam, simply to practice Sam.
Copy the original character s string and add it to the original string and convert it to SS. Then, we need the smallest lexicographic string with the length of SS | S |, so we can construct the SS Sam, starting from root, each time the smallest number is transferred, | S | after the step arrives, it is the requested substring (set to P ), because we require the starting position and the smallest one, we save a variable L in each State to indicate the leftmost position of this State in SS, the answer is P-> L-| S | + 1. below is the code.
#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define maxn 40010using namespace std;char str[maxn>>1];struct sam{ sam *go[26],*par; int val; int l,po;}*root,*tail,que[maxn],*top[maxn];int tot;void add(int c,int l,int po){ sam *p=tail,*np=&que[tot++]; np->po=po; np->val=l; while(p&&p->go[c]==NULL) p->go[c]=np,p=p->par; if(p==NULL) np->par=root; else { sam *q=p->go[c]; if(p->val+1==q->val) np->par=q; else { sam *nq=&que[tot++]; *nq=*q; nq->val=p->val+1; np->par=q->par=nq; while(p&&p->go[c]==q) p->go[c]=nq,p=p->par; } } tail=np;}int c[maxn],len;void init(){ memset(que,0,sizeof(que)); tot=0; len=1; root=tail=&que[tot++];}void solve(int n){ memset(c,0,sizeof(c)); int i; for(i=0;i<tot;i++) c[que[i].val]++; for(i=1;i<len;i++) c[i]+=c[i-1]; for(i=0;i<tot;i++) top[--c[que[i].val]]=&que[i]; for(sam *p=root;;p=p->go[str[p->val+1]-'a']) { p->l=p->po; //printf("%c",str[p->val+1]); if (p->val==len-1)break; } sam *p; for(i=tot-1;i>=0;i--) { p=top[i]; if(p->par) { sam *q=p->par; if(q->l==0||q->l>p->l) q->l=p->l; } } p=root; int tmp=n; while(tmp--) { int i; for(i=0;i<26;i++) { if(p->go[i]) { p=p->go[i]; break; } } } int ans=p->l-n+1; printf("%d\n",ans);}int main(){ //freopen("dd.txt","r",stdin); int ncase; scanf("%d",&ncase); while(ncase--) { scanf("%s",str+1); init(); int l=strlen(str+1),i; for(i=1;i<=l;i++) { str[i+l]=str[i]; } for(i=1;i<=2*l;i++) add(str[i]-'a',len++,i); solve(l); } return 0;}
Here is another code specifically used to calculate the minimum string representation. Simple and effective...
#include <stdio.h>#include <stdlib.h>#include <string.h>#define MAXN 100000int min(int a,int b){ return a<b?a:b;}int min_Str(char *str){ int i,j,k,len=strlen(str); i=0,j=1; memcpy(str+len,str,len); while(j<len&&i<len) { k=0; while(str[i+k]==str[j+k]) k++; if(k>=len) break; if(str[i+k]>str[j+k]) i=i+k+1; else j=j+k+1; if(i==j) j++; } return min(i,j);}char str[MAXN];int main(){ //freopen("dd.txt","r",stdin); int ncase; scanf("%d",&ncase); while(ncase--) { memset(str,'\0',sizeof(str)); scanf("%s",str); printf("%d\n",1+min_Str(str)); } return 0;}