题意:求环形字符串中长度为n的最小字典序子串。
可用后缀数组做。
但这次采用的方法是后缀自动机。
思路:建好自动机,然后跑n步即可找到字典序最小的字符串。
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <math.h>
#include <string.h>
using namespace std;
typedef long long ll;
const int Mod=1e9+7;
const int N=1e4+5;
struct SAM_Node{
SAM_Node *fa,*next[26];
int len;
int id,pos;
SAM_Node(){}
SAM_Node(int _len){
fa=0;len=_len;
memset(next,0,sizeof(next));
}
};
SAM_Node SAM_node[N<<2],*SAM_root,*SAM_last;
int SAM_size;
SAM_Node *newSAM_Node(int len){
SAM_node[SAM_size]=SAM_Node(len);
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}
SAM_Node *newSAM_Node(SAM_Node *p){
SAM_node[SAM_size]=*p;
SAM_node[SAM_size].id=SAM_size;
return &SAM_node[SAM_size++];
}
void SAM_init(){
SAM_size=0;
SAM_root=SAM_last=newSAM_Node(0);
SAM_node[0].pos=0;
}
void SAM_add(int x,int len){
SAM_Node *p=SAM_last,*np=newSAM_Node(p->len+1);
np->pos=len;
SAM_last=np;
for(;p&&!p->next[x];p=p->fa)p->next[x]=np;
if(!p){
np->fa=SAM_root;
//puts("1");
return;
}
SAM_Node *q=p->next[x];
if(q->len==p->len+1){
np->fa=q;
//puts("2");
return;
}
//puts("3");
SAM_Node *nq=newSAM_Node(q);
nq->len=p->len+1;
q->fa=nq;
np->fa=nq;
for(;p&&p->next[x]==q;p=p->fa)p->next[x]=nq;
}
char str[N];
void work(){
int T;
scanf("%d\n",&T);
while(T--){
scanf("%s",str+1);
//printf("%s\n",str+1);
int n=strlen(str+1);
SAM_init();
for(int i=1;i<=n;i++)
SAM_add(str[i]-'a',i);
for(int i=1;i<=n;i++)
SAM_add(str[i]-'a',i);
SAM_Node *cur=SAM_root;
for(int i=1;i<=n;i++){
for(int j=0;j<26;j++)if(cur->next[j]){
cur=cur->next[j];
break;
}
}
printf("%d\n",cur->pos%n+1);
}
}
int main(){
freopen("C_in.txt","r",stdin);
work();
return 0;
}