KMP求出ne数组 然后每个数向他的ne数组连边
求lca就行 记得特判
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb push_back
#define inf 1<<62
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
int n, m , k;
vi g[N];
int siz[N], d[N], top[N], ne[N], son[N], f[N], vis[N] ;
void dfs(int u, int fa) {
d[u] = d[fa] + 1;
f[u] = fa;
siz[u] = 1;
int ma = -1;
for(auto v : g[u]) {
if(v == fa)continue;
dfs(v, u);
siz[u] += siz[v];
if(ma < siz[v]) {
son[u] = v, ma = siz[v];
}
}
}
void dfs2(int u, int ff) {
top[u] = ff;
if(!son[u])return;
dfs2(son[u], ff);
for(auto v : g[u]) {
if(v != f[u] && v != son[u])dfs2(v, v);
}
}
int lca(int x, int y) {
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]])swap(x, y);
x = f[top[x]];
}
return d[x] < d[y] ? x : y;
}
string s;
void add(int x, int y) {
g[x].push_back(y);
g[y].push_back(x);
}
void solve() {
cin >> s;
m = s.size();
s = " " + s;
for(int i = 2, j = 0; i <= m; i++) {
while(j && s[i] != s[j + 1]) j = ne[j];
if(s[i] == s[j + 1])j++;
ne[i] = j;
}
for(int i = m; i >= 1; i--) {
if(!vis[i]) {
vis[i] = 1;
int t = i;
while(1) {
if(!t)break;
add(t, ne[t]);
t = ne[t];
if(vis[t])break;
vis[t] = 1;
}
}
}
dfs(0, m + 1);
//de_bug(son[0]);
dfs2(0, 0);
int q;
cin >> q;
while(q--) {
int x, y;
cin >> x >> y;
int LCA = lca(x, y);
if(LCA == x || LCA == y)LCA = f[LCA];
cout << LCA << endl;
}
}
int main() {
IOS;
int _ = 1;
//cin>>_;
while( _-- )
solve();
}