题链:
题解:
给出一个字符串,有一个操作:把首字符放到末尾,形成新的串。求任意次操作后,字典序最小的串的首字母在原串中的位置。(这就是最小表示法?哈)
把原串翻倍,建立后缀自动机。然后在自动机上从起点往当前节点的较小的字母上跑len步即可。代码:
#include#include #include #define MAXN 40050#define filein(x) freopen(#x".in","r",stdin);#define fileout(x) freopen(#x".out","w",stdout);using namespace std;struct SAM{ int size,last,p,q,np,nq; int step[MAXN],pre[MAXN],ch[MAXN][26]; int newnode(int a,int b){ step[size]=a; memcpy(ch[size],ch[b],sizeof(ch[b])); return size++; } void add(int x){ p=last; last=np=newnode(step[p]+1,0); while(p&&!ch[p][x]) ch[p][x]=np,p=pre[p]; if(!p) pre[np]=1; else{ q=ch[p][x]; if(step[p]+1!=step[q]){ nq=newnode(step[p]+1,q); pre[nq]=pre[q]; pre[q]=pre[np]=nq; while(p&&ch[p][x]==q) ch[p][x]=nq,p=pre[p]; } else pre[np]=q; } } void build(char *S){ memset(ch[0],0,sizeof(ch[0])); size=1; last=newnode(-1,0); for(int i=0;S[i];i++) add(S[i]-'a'); }}suf;int find(int len){ int p=1; for(int i=0;i