其实这个题也可以用最小表示法
但是还是练了练后缀自动机
明白了构造函数就是构造原串(整个串)的以最后一个字符为止的所有后缀都加上一个字符产生新串的后缀
这个题目就是找这个字符串循环中的最小表示
直接两个原串一拼接 所有的循环都是拼接后长串的后缀
找到长度为len的最小后缀即可
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int maxn = 20000+100;
int tot = 1;
int las = 1;
struct NODE{
int ch[26];
int len,fa;
NODE(){
memset(ch,0,sizeof(ch));
len = fa = 0;
}
}dian[maxn];
int pos[maxn*2];
void add(int c,int _pos){
int p = las;
int np = las = ++tot;
pos[np] = _pos;
dian[np].len = dian[p].len+1;
for(;p&&!dian[p].ch[c];p = dian[p].fa)dian[p].ch[c] = np;
if(!p)dian[np].fa = 1;
else{
int q = dian[p].ch[c];
if(dian[q].len == dian[p].len+1){
dian[np].fa = q;
}
else{
int nq = ++tot;
pos[nq] = _pos;
dian[nq] = dian[q];
dian[nq].len = dian[p].len+1;
dian[q].fa = dian[np].fa = nq;
for(;p&&dian[p].ch[c]==q;p = dian[p].fa)dian[p].ch[c] = nq;
}
}
}
char s[maxn*2];
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(dian,0,sizeof(dian));
tot = las = 1;
scanf("%s",s);
int len = strlen(s);
for(int i = len;i<len+len;++i){
s[i] = s[i-len];
}
for(int i = 0;i<len+len;++i){
add(s[i]-'a',i);
}
int st = 1;
for(int i = 0;i<len;++i){
for(int j = 0;j<26;++j){
if(dian[st].ch[j]){
st = dian[st].ch[j];
//cout<<pos[st]<<endl;
break;
}
}
}
int ind = pos[st];
// cout<<ind<<endl;
printf("%d\n",ind-len+2);
}
}