今天就整理模板吧
感谢牛逼网友的帮助,有了这些模板整理工具:
https://github.com/4thcalabash/code_library
http://www.planetb.ca/syntax-highlight-word
https://www.cnblogs.com/palayutm/p/6444833.html#e5898de8a880_2
https://github.com/wx-csy/code_library
先把所有的需要的东西放到这,然后再整理、打印
Vim配置:
windows:
syntax on
set backspace=indent,eol,start
set nu si ci ai mouse=a sw=4 sts=4 ts=4
set hlsearch incsearch
colorscheme desert
set guifont=Consolas:h12
set report=0 showmatch cursorline
set guioptions-=m
set guioptions-=T
nmap ggvG
vmap "*y
nmap : vs %<.in
nmap : vs %<.out
nmap : !%<
nmap : !%< < %<.in
nmap : !g++ % -o %< -std=c++11
:cd D:\cpp
ubantu:
set nu ai ci si sts=4 ts=4 sw=4 mouse=a
nmap : vs %<.in
nmap : !clear && time ./%< < %<.in
nmap : vs %<.out
nmap : !clear && g++ -std=c++11 % -o %<
nmap : !clear && time ./%<
nmap ggvG$
vmap "+y
nmap "+gp
imap "+pa
头文件、预操作:
#include
#include
快速读入、输出:
inline int read(){
char ch = getchar();
int x = 0, f = 1;
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while('0' <= ch && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void write(int x){
if (x < 0) x = ~x + 1, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
LCS:
char s[maxn], t[maxn];
int dp[maxn][maxn];
int n = strlen(s + 1), m = strlen(t + 1);
rep(i, 1, n){
rep(j, 1, m){
if(s[i] == t[j]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
printf("%d\n", dp[n][m]);
LIS:
fill(dp, dp + n + 1, inf);
rep(i, 1, n){
*lower_bound(dp + 1, dp + n + 1, a[i]) = a[i];
}
printf("%d\n", lower_bound(dp + 1, dp + n + 1, inf) - dp - 1);
Bellman_Ford:
struct edge{
int from, to, cost;
}e[maxn];
int d[maxn];
bool Bellman_Frod(int s){
memset(d, 0, sizeof(d));
rep(i, 1, n){
rep(j, 1, m){
edge t = e[j];
if(d[t.to] > d[t.from] + t.cost){
d[t.to] = d[t.from] + t.cost;
if(i == n) return true;
}
}
}
return false;
}
Dijkstra+heap:
struct edge{
int to, cost;
edge(){}
edge(int to, int cost){
this->to = to, this->cost = cost;
}
};
vector G[maxn];
int d[maxn];
int n, m;
void dij(int s){
priority_queue, greater > q;
fill(d, d + n + 1, inf);
d[s] = 0;
q.push(PII(0, s));
while(!q.empty()){
PII p = q.top(); q.pop();
int v = p.se;
if(d[v] < p.fi) continue;
int len = G[v].size();
rep(i, 0, len - 1){
edge e = G[v][i];
if(d[e.to] > d[v] + e.cost){
d[e.to] = d[v] + e.cost;
q.push(PII(d[e.to], e.to));
}
}
}
}
MST:
struct edge{
int u, v, cost;
friend bool operator < (edge a, edge b){
return a.cost < b.cost;
}
};
edge es[maxm];
int fa[maxn];
int n, m;
int Find(int x){ return fa[x] == x ? x : fa[x] = Find(fa[x]); }
void uni(int x, int y){ fa[Find(x)] = Find(y); }
void init(){ rep(i, 0, n + 1) fa[i] = i; }
int solve(){
init();
sort(es + 1, es + m + 1);
int res = 0;
rep(i, 1, m){
edge e = es[i];
if(Find(e.u) != Find(e.v)){
uni(e.u, e.v);
res += e.cost;
}
}
return res;
}
次小生成树:
#define int ll
struct edge{
int from, to, val;
friend bool operator <(edge a, edge b){
return a.val < b.val;
}
}es[maxn];
vector G[maxn];
bool vis[maxn];
int fa[maxn], dep[maxn], acst[maxn][22];
int Max1[maxn][22], Max2[maxn][22];
int lg[maxn];
int n, m;
int Find(int x) { return fa[x] == x ? x : fa[x] = Find(fa[x]); }
void uni(int x, int y) { fa[Find(x)] = Find(y); }
void init() {
//memset(dep, 0, sizeof(dep));
//memset(acst, 0, sizeof(acst));
//memset(Max1, 0, sizeof(Max1));
//memset(Max2, 0, sizeof(Max2));
//rep(i, 0, n) vis[i] = 0;
rep(i, 0, n) fa[i] = i;
//rep(i, 0, n) G[i].clear();
rep(i, 1, n){
lg[i] = lg[i-1] + ((1 << lg[i-1]) == i);
}
}
void dfs(int x){
int len = G[x].size();
rep(i, 0, len - 1){
int y = G[x][i];
int nxt = es[y].from == x ? es[y].to : es[y].from;
int val = es[y].val;
if(acst[x][0] == nxt) continue;
acst[nxt][0] = x, Max1[nxt][0] = val;
dep[nxt] = dep[x] + 1;
dfs(nxt);
}
}
void work(){
rep(j, 1, 19){
rep(i, 1, n){
acst[i][j] = acst[acst[i][j-1]][j-1];
Max1[i][j] = max(Max1[i][j-1], Max1[acst[i][j-1]][j-1]);
Max2[i][j] = max(Max2[i][j-1], Max2[acst[i][j-1]][j-1]);
if(Max1[i][j-1] != Max1[acst[i][j-1]][j-1]) Max2[i][j] = max(Max2[i][j], min(Max1[i][j-1], Max1[acst[i][j-1]][j-1]));
}
}
}
int MAX(int x, int a, int b, int val)
{
if(val > Max1[a][b]) return max(x, Max1[a][b]);
return max(x, Max2[a][b]);
}
int Get(int x, int y, int val){
if(dep[x] < dep[y]) swap(x, y);
int i, res = 0;
while(dep[x] > dep[y]) {
i = lg[dep[x]-dep[y]] - 1;
res = MAX(res, x, i, val);
x = acst[x][i];
}
if(x == y) return res;
i = 0;
while(acst[x][i] != acst[y][i]) i++;
for( ; i >= 0; i--){
if(acst[x][i] != acst[y][i]) {
res = MAX(MAX(res, x, i, val), y, i, val);
x = acst[x][i], y = acst[y][i];
}
}
return MAX(MAX(res, x, 0, val), y, 0, val);
}
int32_t main()
{
scanf("%lld %lld", &n, &m);
init();
rep(i, 1, m){
scanf("%lld %lld %lld", &es[i].from, &es[i].to, &es[i].val);
}
sort(es + 1, es + m + 1);
int res = 0, cnt = 0;
rep(i, 1, m){
if(cnt >= n) break;
int fu = Find(es[i].from), fv = Find(es[i].to);
if(fu != fv){
vis[i] = 1;
uni(fu, fv);
res += es[i].val;
cnt++;
G[es[i].from].pb(i);
G[es[i].to].pb(i);
}
}
dep[1] = 1, dfs(1);
work();
int ans = INF, t;
rep(i, 1, m){
if(!vis[i]){
t = Get(es[i].from, es[i].to, es[i].val);
ans = min(ans, res + es[i].val - t);
}
}
printf("%lld\n", ans);
return 0;
}
树状数组:
int c[maxn];
int getsum(int x){
int ret = 0;
for( ; x > 0; ret += c[x], x -= lowbit(x));
return ret;
}
void update(int x, int val){
for ( ; x <= maxn; c[x] += val, x += lowbit(x));
}
最大流:
FF:
struct edge{
int to, cap, rev;
};
vector G[maxn];
bool vis[maxn];
void add_edge(int from, int to, int cap){
G[from].pb((edge){to, cap, G[to].size()});
G[to].pb((edge){from, 0, G[from].size() - 1});
}
int dfs(int v, int t, int f){
if(v == t) return f;
vis[v] = 1;
rep(i, 0, G[v].size() - 1){
edge &e = G[v][i];
if(!vis[e.to] && e.cap > 0){
int d = dfs(e.to, t, min(f, e.cap));
if(d > 0){
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t){
int flow = 0;
for( ; ; ){
memset(vis, 0, sizeof(vis));
int f = dfs(s, t, inf);
if(f == 0) return flow;
flow += f;
}
}
Dinic:
int n, m, k, cnt;
struct node{
int next = -1;
int to;
int w;
};
int head[maxn], dep[maxn];
int d[805][805], pos[maxn];
node edge[maxn];
void init(){
cnt = -1;
memset(head, -1, sizeof(head));
}
void add_edge(int x, int y, int z){
cnt++;
edge[cnt].to = y;
edge[cnt].next = head[x];
edge[cnt].w = z;
head[x] = cnt;
}
//x->y一条容量为z的边做法:
//add_edge(x, y, z), add_edge(y, x, 0)
int bfs(){
memset(dep, 0, sizeof(dep));
queue q;
while(!q.empty()) q.pop();
dep[s] = 1;
q.push(s);
do{
int u = q.front();
q.pop();
for(int i = head[u]; i != -1; i = edge[i].next){
if(edge[i].w > 0 && dep[edge[i].to] == 0){
dep[edge[i].to] = dep[u] + 1;
q.push(edge[i].to);
}
}
}while(!q.empty());
return dep[t] != 0;
}
int dfs(int u, int dist){
if(u == t) return dist;
for(int i = head[u]; i != -1; i = edge[i].next){
if((dep[edge[i].to] == dep[u] + 1) && (edge[i].w != 0)){
int di = dfs(edge[i].to, min(dist, edge[i].w));
if(di > 0){
edge[i].w -= di;
edge[i^1].w += di;
return di;
}
}
}
return 0;
}
int dinic()
{
int ans = 0;
while(bfs()) while(int di = dfs(s, inf)) ans += di;
return ans;
}
计算几何:(有待完善)
inline int sign(db a) { return a < -eps ? -1 : a > eps; }//判断符号
inline bool dcmp(db x, db y){ return fabs(x - y) < eps ? 1 : 0; }
inline db add(db a, db b){ return fabs(a + b) < eps * (fabs(a) + fabs(b)) ? 0 : a + b; }
inline int cmp(db a, db b) { return sign(a - b); }
struct P{
db x, y;
P() {}
P(db x, db y) : x(x), y(y) {}
P operator + (P p) { return P(add(x, p.x), add(y, p.y)); }
P operator - (P p) { return P(add(x, -p.x), add(y, -p.y)); }
P operator * (db d) { return P(x * d, y * d); }
P operator / (db d) { return P(x / d, y / d); }
bool operator == (P p) { return dcmp(p.x, x) && dcmp(p.y, y); }
bool operator != (P p) { return !dcmp(p.x, x) || !dcmp(p.y, y); }
bool operator < (P p) const{//具体而定
if(dcmp(x, p.x)) return y < p.y;
return x < p.x;
}
db dot(P p) { return x * p.x + y * p.y; }
db det(P p) { return x * p.y - y * p.x; }
db abs() { return sqrt(x * x + y * y); }
db abs2() { return x * x + y * y; }
db getw() { return atan2(y, x); }
};
db Length(P a) { return sqrt(a.dot(a)); }//模
db angle(P p1, P p2){ return atan2l(p1.det(p2), p1.dot(p2)); }//夹角的弧度值
db cross(P p1, P p2, P p3) { return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y); }
int crossOp(P p1, P p2, P p3) { return sign(cross(p1, p2, p3)); }
bool chkLL(P p1, P p2, P q1, P q2){//直线平行
db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
return !sign(a1 + a2);
}
P proj(P p1, P p2, P q){//q到直线p1-p2的投影点
P dir = p2 - p1;
return p1 + dir * (dir.dot(q - p1) / dir.abs2());
}
bool intersect(db l1, db r1, db l2, db r2){//为后面用
if(l1 > r1) swap(l1, r1);
if(l2 > r2) swap(l2, r2);
return !(cmp(r1, l2) == -1 || cmp(r2, l1) == -1);
}
bool isSS(P p1, P p2, P q1, P q2){//线段相交
return intersect(p1.x, p2.x, q1.x, q2.x) && intersect(p1.y, p2.y, q1.y, q2.y) &&
crossOp(p1, p2, q1) * crossOp(p1, p2, q2) <= 0 &&
crossOp(q1, q2, p1) * crossOp(q1, q2, p2) <= 0;
}
bool isSS_strict(P p1, P p2, P q1, P q2){//严格相交
return crossOp(p1, p2, q1) * crossOp(p1, p2, q2) <= 0 &&
crossOp(q1, q2, p1) * crossOp(q1, q2, p2) <= 0;
}
bool isMiddle(db a, db m, db b){
return sign(a - m) == 0 || sign(b - m) == 0 || (a < m != b < m);
}
bool isMiddle(P a, P m, P b){
return isMiddle(a.x, m.x, b.x) && isMiddle(a.y, m.y, b.y);
}
bool on_seg(P p1, P p2, P q){//判断点q在线段p1-p2上
return crossOp(p1, p2, q) == 0 && isMiddle(p1, q, p2);
}
bool on_seg_strict(P p1, P p2, P q){
return crossOp(p1, p2, q) == 0 && sign((q - p1).dot(p1 - p2)) * sign((q - p2).dot(p1 - p2)) < 0;
}
P getLL(P p1, P p2, P q1, P q2){//直线p1-p2, q1-q2的交点
db a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
return (p1 * a2 + p2 * a1) / (a1 + a2);
}
矩阵快速幂:
struct Matrix
{
int mat[maxn][maxn];
Matrix() {}
Matrix operator*(Matrix const &b)const
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0 ;i < maxn; i++)
for (int j = 0; j < maxn; j++)
for (int k = 0; k < maxn; k++)
res.mat[i][j] = (res.mat[i][j]+this->mat[i][k] * b.mat[k][j])%mod;
return res;
}
};
Matrix pow_mod(Matrix base, int n)
{
Matrix res;
memset(res.mat, 0, sizeof(res.mat));
for (int i = 0; i < maxn; i++)
res.mat[i][i] = 1;
while (n > 0)
{
if (n & 1) res = res*base;
base = base*base;
n >>= 1;
}
return res;
}
int main()
{
Matrix base;
for(int i = 0; i < maxn; i++){
for(int j = 0; j < maxn; j++){
base.mat[i][j] = 1;
}
}
base.mat[1][1] = 0;
int n;
while(~scanf("%d", &n) && (n + 1)){
Matrix ans = pow_mod(base, n);
printf("%d\n", ans.mat[0][1]);
}
return 0;
}
倍增LCA:
vector G[maxn];
bool vis[maxn];
int lg[maxn], dep[maxn];
int acst[maxn][22];
int n;
void dfs(int u, int fa){
int len = G[u].size();
acst[u][0] = fa;
for(int i = 1; (1 << i) <= dep[u]; i++){
acst[u][i] = acst[acst[u][i-1]][i-1];
}
rep(i, 0, len - 1){
int v = G[u][i];
if(v != fa){
dep[v] = dep[u] + 1;
dfs(v, u);
}
}
}
int LCA(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
while(dep[x] > dep[y]) {
x = acst[x][lg[dep[x]-dep[y]]-1];
}
if(x == y) return x;
Rep(k, lg[dep[x]] - 1, 0){
if(acst[x][k] != acst[y][k]) x = acst[x][k], y = acst[y][k];
}
return acst[x][0];
}
void init(){
rep(i, 1, n){
lg[i] = lg[i-1] + ((1 << lg[i-1]) == i);
}
}
Manacher:
char Ma[maxn*2];
int p[maxn*2];
void Manacher(char s[], int len){
int l = 0;
Ma[l++] = '$';
Ma[l++] = '#';
rep(i, 0, len - 1){
Ma[l++] = s[i];
Ma[l++] = '#';
}
Ma[l] = 0;
int mx = 0, id = 0;
rep(i, 0, l - 1){
p[i] = mx > i ? min(p[2*id-i], mx - i) : 1;
while(Ma[i+p[i]] == Ma[i-p[i]]) p[i]++;
if(i + p[i] > mx){
mx = i + p[i];
}
id = i;
}
}
char s[maxn];
int main()
{
scanf("%s", s);
int len = strlen(s);
Manacher(s, len);
int ans = 0;
rep(i, 0, 2 * len + 1) ans = max(ans, p[i] - 1);
return 0;
}
最大权闭合子图:
//首先建模,一个超级源点和一个超级汇点,源点和正权点连边,汇点和负权点连边,权值就是点值,图中的所有关系边边权为inf,结论就是最大权闭合子图的权值为 所有正点权之和减去最小割的权值和
//然后跑最大流就是答案
计算组合数:
费马小定理:
ll fac[maxn];
ll qpow(ll x, ll y){
ll res = 1;
while(y){
if(y & 1) res = (res * x) % mod;
y >>= 1;
x = (x * x) % mod;
}
return res;
}
void init(){
fac[0] = 1;
for(int i = 1; i < maxn; i++){
fac[i] = fac[i-1] * i % mod;
}
}
ll Com(ll n,ll m){
init();
if(m > n || m < 0) return 0;
ll a = fac[n], b = fac[n-m] * fac[m] % mod;
return a * qpow(b, mod - 2) % mod;
}
打表:
ll C[maxn][maxn];
void init(){
rep(i, 0, 5000){
rep(j, 0, i){
C[i][j] = 1;
}
}
rep(i, 2, 5000){
rep(j, 1, i){
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
}
}
}
字符串最小表示:
int n = strlen(s + 1);
rep(i, 1, n) s[n+i] = s[i];
int i = 1, j = 2, k;
while(i <= n && j <= n){
for(k = 0; k < n && s[i+k] == s[j+k]; k++);
if(k == n) break;
if(s[i+k] > s[j+k]){
i = i + k + 1;
if(i == j) i++;
} else {
j = j + k + 1;
if(i == j) j++;
}
}
int ans = min(i, j);
主席树:
int a[maxn], b[maxn];
int L[20*maxn], R[20*maxn];
int T[maxn], sum[20*maxn];
int n, m, q, tot = 0;
inline int build(int l, int r){
int rt = ++tot;
if(l < r){
int mid = (l + r) >> 1;
L[rt] = build(l, mid);
R[rt] = build(mid + 1, r);
}
return rt;
}
inline int update(int pre, int l, int r, int x){
int rt = ++tot;
L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre] + 1;
if(l < r){
int mid = (l + r) >> 1;
if(x <= mid) L[rt] = update(L[pre], l, mid, x);
else R[rt] = update(R[pre], mid + 1, r, x);
}
return rt;
}
inline int query(int u, int v, int l, int r, int k){
if(l == r) return l;
int x = sum[L[v]] - sum[L[u]], mid = (l + r) >> 1;
if(x >= k) return query(L[u], L[v], l, mid, k);
else return query(R[u], R[v], mid + 1, r, k - x);
}
int main()
{
int t; scanf("%d", &t);
while(t--){
tot = 0;
scanf("%d %d", &n, &q);
rep(i, 1, n) scanf("%d", a + i), b[i] = a[i];
sort(b + 1, b + n + 1);
m = unique(b + 1, b + n + 1) - b - 1;
T[0] = build(1, m);
rep(i, 1, n){
a[i] = lower_bound(b + 1, b + m + 1, a[i]) - b;
T[i] = update(T[i-1], 1, m, a[i]);
}
while(q--){
int l, r, k; scanf("%d %d %d", &l, &r, &k);
int p = query(T[l-1], T[r], 1, m, k);
printf("%d\n", b[p]);
}
}
return 0;
}
KMP:
//主串a, 模式串b, 输出所有出现的位置以及nxt数组
char a[maxn], b[maxn];
int nxt[maxn];
int main()
{
scanf("%s %s", a + 1, b + 1);
int la = strlen(a + 1), lb = strlen(b + 1);
int j = 0;
rep(i, 2, lb){
while(j && b[i] != b[j+1]) j = nxt[j];
if(b[j+1] == b[i])j++;
nxt[i] = j;
}
j = 0;
rep(i, 1, la){
while(j > 0 && b[j+1] != a[i]) j = nxt[j];
if(b[j+1] == a[i]) j++;
if(j == lb) printf("%d\n", i - lb + 1), j = nxt[j];
}
rep(i, 1, lb) printf("%d ", nxt[i]);
return 0;
}
AC自动机:
//n个模式串和一个主串,输出有多少模式串出现过
queue q;
struct Aho_Corasick_Automaton{
int c[maxn][26], val[maxn], fail[maxn], cnt;
void ins(char *s){
int len = strlen(s), now = 0;
rep(i, 0, len - 1){
int v = s[i] - 'a';
if(!c[now][v]) c[now][v] = ++cnt;
now = c[now][v];
}
val[now]++;
}
void build(){
rep(i, 0, 25) if(c[0][i]) fail[c[0][i]] = 0, q.push(c[0][i]);
while(!q.empty()){
int u = q.front(); q.pop();
rep(i, 0, 25) if(c[u][i]) fail[c[u][i]] = c[fail[u]][i], q.push(c[u][i]);
else c[u][i] = c[fail[u]][i];
}
}
int query(char *s){
int len = strlen(s), now = 0, ans = 0;
rep(i, 0, len - 1){
now = c[now][s[i]-'a'];
for(int t = now; t && ~val[t]; t = fail[t]) ans += val[t], val[t] = -1;
}
return ans;
}
}AC;
char p[1000005];
int n;
int main()
{
scanf("%d",&n);
rep(i, 1, n) scanf("%s", p), AC.ins(p);
AC.build();
scanf("%s", p);int ans = AC.query(p);
printf("%d\n", ans);
return 0;
}
后缀数组:
//读入一个长度为n的由大小写英文字母或数字组成的字符串,请把这个字符串的所有非空后缀按字典序从小到大排序,然后按顺序输出后缀的第一个字符在原串中的位置。位置编号为 1 到 n
char s[maxn];
int n, m, rak[maxn], sa[maxn], tax[maxn], tp[maxn];
void Qsort() {
rep(i, 0, m) tax[i] = 0;
rep(i, 1, n) tax[rak[i]]++;
rep(i, 1, m) tax[i] += tax[i-1];
Rep(i, n, 1) sa[tax[rak[tp[i]]]--] = tp[i];
}
void SuffixSort() {
m = 75;
rep(i, 1, n) rak[i] = s[i] - '0' + 1, tp[i] = i;
Qsort();
for(int w = 1, p = 0; p < n; m = p, w <<= 1) {
//w:当前倍增的长度,w = x表示已经求出了长度为x的后缀的排名,现在要更新长度为2x的后缀的排名
//p表示不同的后缀的个数,很显然原字符串的后缀都是不同的,因此p = n时可以退出循环
p = 0;//这里的p仅仅是一个计数器000
rep(i, 1, w) tp[++p] = n - w + i;
rep(i, 1, n) if (sa[i] > w) tp[++p] = sa[i] - w; //这两句是后缀数组的核心部分,我已经画图说明
Qsort();//此时我们已经更新出了第二关键字,利用上一轮的rak更新本轮的sa
std::swap(tp, rak);//这里原本tp已经没有用了
rak[sa[1]] = p = 1;
rep(i, 2, n) rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w]) ? p : ++p;
//这里当两个后缀上一轮排名相同时本轮也相同,至于为什么大家可以思考一下
}
rep(i, 1, n) printf("%d ", sa[i]); puts("");
}
int main()
{
scanf("%s", s + 1);
n = strlen(s + 1);
SuffixSort();
return 0;
}
字符串hash:
//求区间不相同子串个数
const int Hash = 10007;
const int maxn = 2100;
struct hashmap{
int head[Hash],nxt[maxn],size;
unsigned long long state[maxn];
int f[maxn];
void init(){
size = 0;
memset(head, -1, sizeof(head));
}
int insert(unsigned long long val,int id){
int h = val % Hash;
for(int i = head[h]; i != -1; i = nxt[i]){
if(val == state[i]){
int temp = f[i];
f[i] = id;
return temp;
}
}
f[size] = id;
state[size] = val;
nxt[size] = head[h];
head[h] = size++;
return 0;
}
} h;
const int seed = 13331;
unsigned long long P[maxn];
unsigned long long S[maxn];
char str[maxn];
int ans[maxn][maxn];
int main()
{
P[0] = 1;
rep(i, 1, maxn - 1) P[i] = P[i-1] * seed;
int T; scanf("%d", &T);
while(T--){
scanf("%s", str);
int n = strlen(str);
rep(i, 1, n) S[i] = S[i-1] * seed + str[i-1];
memset(ans, 0, sizeof(ans));
rep(L, 1, n){
h.init();
rep(i, 1, n - L + 1){
int l = h.insert(S[i+L-1] - S[i-1] * P[L], i);
ans[i][i+L-1]++;
ans[l][i+L-1]--;
}
}
Rep(i, n, 0)
rep(j, i, n)
ans[i][j] += ans[i+1][j] + ans[i][j-1] - ans[i+1][j-1];
int Q; scanf("%d",&Q);
while(Q--){
int a,b;
scanf("%d%d", &a, &b);
printf("%d\n", ans[a][b]);
}
}
return 0;
}