Problem Description


Alice gets N strings. Now she has Q questions to ask you. For each question, she wanna know how many different prefix strings between Lth and Rth strings. It's so easy right? So solve it!


 



Input


The input contains multiple test cases.

For each test case, the first line contains one integer  N(1≤N≤100000). Then next N lines contain N strings and the total length of N strings is between 1 and 100000. The next line contains one integer  Q(1≤Q≤100000). We define a specail integer Z=0. For each query, you get two integer L, R(0=<L,R<N). Then the query interval [L,R] is [min((Z+L)%N,(Z+R)%N)+1,max((Z+L)%N,(Z+R)%N)+1]. And Z change to the answer of this query.


 



Output


For each question, output the answer.


 



Sample Input


3 abc aba baa 3 0 2 0 1 1 1


 



Sample Output


7 6 3



前缀最多久10w个,可以用tire或者hash把每个串代表的前缀弄出来,然后就是询问区间内不同数字个数


这个离线的时候可以用树状数组和线段树搞定,在线的话,只要把持久化即可,用主席树就ok了


#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
using namespace std;
typedef __int64 LL;
const int low(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 0x7FFFFFFF;
const int mod = 998244353;
const int N = 1e5 + 10;
int n, q, sz, l, r;
int f[N][26], pre[N], rt[N], L[N * 40], R[N * 40], a[N * 40], t;
char s[N];

int clear(int x)
{
if (x == 0)
{
L[t] = R[t] = a[t] = 0;
return t++;
}
else
{
memset(f[sz], 0, sizeof(f[sz]));
pre[sz] = 0;
return sz++;
}
}

void add(int now, int u, int v)
{
int x = clear(0), y = rt[now], z = x;
int l = 1, r = n;

while (l <= r)
{
a[x] = a[y] + v;
L[x] = L[y]; R[x] = R[y];

if (l == r) break;
int mid = l + r >> 1;

if (u <= mid)
{
x = L[x] = clear(0); y = L[y]; r = mid;
}
else
{
x = R[x] = clear(0); y = R[y]; l = mid + 1;
}
}
rt[now] = z;
}

int get(int x, int l, int r, int ll, int rr)
{
if (ll <= l&&r <= rr) return a[x];
int mid = l + r >> 1, res = 0;
if (ll <= mid) res += get(L[x], l, mid, ll, rr);
if (rr > mid) res += get(R[x], mid + 1, r, ll, rr);
return res;
}

int main()
{
while (scanf("%d", &n) != EOF)
{
t = sz = 0;
clear(0); clear(1);
rep(i, 1, n)
{
scanf("%s", s);
rt[i] = rt[i - 1];
for (int j = 0, k = 0; s[j]; j++)
{
if (!f[k][s[j] - 'a']) f[k][s[j] - 'a'] = clear(1);
k = f[k][s[j] - 'a'];
add(i, pre[k] + 1, 1);
pre[k] = i;
}
if (i < n) add(i, i + 1, -strlen(s));
}
scanf("%d", &q);
int Z = 0, X, Y;
while (q--)
{
scanf("%d%d", &l, &r);
X = (Z + l) % n + 1;
Y = (Z + r) % n + 1;
if (X > Y) swap(X, Y);
printf("%d\n", Z = get(rt[Y], 1, n, 1, X));
}
}
return 0;
}