AC自动机
Magical String 代码
将 (s) 缩成最小循环节,特判只有一种字符情况,为 (b_i) 建立AC自动机,静态标记 ( t Dfs+bitset+vector) 得出每个 (b_i) 在 (s) 中出现的位置,将它们模 (s) 的长度作为边建图,用 ( t Bfs) 求无向无权图最小环。
P.S. 模板
//ACAM
int ch[M][26],cnt=1,at[N];
vector<int> f[M];
bitset<1000> vis[M];
void insert(int i,int an,string a){
int p=0;
for(int i=0;i<an;i++){
int c=a[i]-'a';
if(!ch[p][c]) ch[p][c]=cnt++;
p=ch[p][c];
}
at[i]=p;
}
int fa[M];
void Getac(){
queue<int> q;
for(int i=0;i<26;i++)
if(ch[0][i]) q.push(ch[0][i]);
while(sz(q)){
int p=q.front(); q.pop();
for(int c=0;c<26;c++)
if(ch[p][c]){
fa[ch[p][c]]=ch[fa[p]][c];
q.push(ch[p][c]);
} else ch[p][c]=ch[fa[p]][c];
}
}
vector<int> ac[M];
void Dfs(int p){
for(int v:ac[p]){
Dfs(v);
for(int x:f[v])if(!vis[p][x])
f[p].pb(x),vis[p][x]=true;
}
}
void Runac(){
int p=0;
for(int i=0;i<len;i++){
p=ch[p][ss[i]-'a'];
f[p].pb(i);
}
// cout<<"?
";
for(int i=1;i<cnt;i++){
ac[fa[i]].pb(i);
assert(fa[i]!=i);
}
Dfs(0);
for(int i=0;i<n;i++)
for(int x:f[at[i]]) add(x-sz(b[i]),x);
}