题目链接
题解
裸题
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 500005,maxm = 100005,INF = 0x3f3f3f3f;
LL P = 23333333333333333ll;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = 0; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 1) + (out << 3) + c - 48; c = getchar();}
return flag ? out : -out;
}
char s[maxn];
int n,m,q;
int sa[maxn],rank[maxn],height[maxn],t1[maxn],t2[maxn],bac[maxn];
int mn[maxn][19],bin[50],Log[maxn];
void getsa(){
int *x = t1,*y = t2; m = 255;
for (int i = 0; i <= m; i++) bac[i] = 0;
for (int i = 1; i <= n; i++) bac[x[i] = s[i]]++;
for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (int i = n; i; i--) sa[bac[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1){
int p = 0;
for (int i = n - k + 1; i <= n; i++) y[++p] = i;
for (int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
for (int i = 0; i <= m; i++) bac[i] = 0;
for (int i = 1; i <= n; i++) bac[x[y[i]]]++;
for (int i = 1; i <= m; i++) bac[i] += bac[i - 1];
for (int i = n; i; i--) sa[bac[x[y[i]]]--] = y[i];
swap(x,y);
x[sa[1]] = p = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
if (p >= n) break;
m = p;
}
for (int i = 1; i <= n; i++) rank[sa[i]] = i;
for (int i = 1,k = 0; i <= n; i++){
if (k) k--;
int j = sa[rank[i] - 1];
while (s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
for (int i = 1; i <= n; i++) mn[i][0] = height[i];
for (int j = 1; j <= 18; j++)
for (int i = 1; i <= n; i++){
if (i + bin[j] - 1 > n) break;
mn[i][j] = min(mn[i][j - 1],mn[i + bin[j - 1]][j - 1]);
}
}
int lcp(int x,int y){
if (x == y) return n - x + 1;
x = rank[x],y = rank[y];
if (x > y) swap(x,y);
x++;
int t = Log[y - x + 1];
return min(mn[x][t],mn[y - bin[t] + 1][t]);
}
int pos[maxn],tot;
int st[maxn],L[maxn],num[maxn],top;
LL ans[maxn];
inline bool cmp(const int& a,const int& b){
return rank[a] < rank[b];
}
void work(){
sort(pos + 1,pos + 1 + tot,cmp);
LL re = 0; top = 0;
int cnt,tmp;
for (int i = 2; i <= tot; i++){
if (pos[i] == pos[i - 1]) continue;
tmp = lcp(pos[i],pos[i - 1]);
cnt = 1;
while (top && tmp <= L[top])
cnt += num[top--];
st[++top] = pos[i - 1];
num[top] = cnt;
L[top] = tmp;
ans[top] = (ans[top - 1] + 1ll * L[top] * num[top] % P) % P;
re = (re + ans[top]) % P;
}
printf("%lld\n",re);
}
int main(){
bin[0] = 1; for (int i = 1; i <= 20; i++) bin[i] = bin[i - 1] << 1;
Log[0] = -1; for (int i = 1; i < maxn; i++) Log[i] = Log[i >> 1] + 1;
n = read(); q = read();
scanf("%s",s + 1);
getsa();
while (q--){
tot = read();
REP(i,tot) pos[i] = read();
work();
}
return 0;
}