1+ #include < bits/stdc++.h>
2+
3+ using namespace std ;
4+ typedef long long ll;
5+
6+ vector<int > pre ;
7+ const int N = 1e5 + 10 ;
8+
9+ char str[N << 1 ];
10+ int w, sa[N], rk[N << 1 ], oldrk[N << 1 ];
11+ vector<int > height (N * 2 , 0 );
12+
13+ void getsa (string s) {
14+ // int i, p;
15+ int n = s.size ();
16+ for (int i = 0 ; i < n; ++i) {
17+ str[i + 1 ] = s[i];
18+ }
19+ for (int i = 1 ; i <= n; ++i) {
20+ sa[i] = i;
21+ rk[i] = str[i];
22+ }
23+
24+ for (w = 1 ; w < n; w <<= 1 ) {
25+ sort (sa + 1 , sa + n + 1 , [](int x, int y) {
26+ return rk[x] == rk[y] ? rk[x + w] < rk[y + w] : rk[x] < rk[y];
27+ });
28+ memcpy (oldrk, rk, sizeof (rk));
29+ for (int p = 0 , i = 1 ; i <= n; ++i) {
30+ if (oldrk[sa[i]] == oldrk[sa[i - 1 ]] &&
31+ oldrk[sa[i] + w] == oldrk[sa[i - 1 ] + w]) {
32+ rk[sa[i]] = p;
33+ } else {
34+ rk[sa[i]] = ++p;
35+ }
36+ }
37+ }
38+ if (n == 1 ) rk[1 ] = 1 ;
39+
40+ // 处理 height 数组
41+ for (int i = 1 , k = 0 ; i <= n; ++i) {
42+ if (rk[i] == 0 ) continue ;
43+ if (k) --k;
44+ while (str[i + k] == str[sa[rk[i] - 1 ] + k]) ++k;
45+ height[rk[i]] = k;
46+ }
47+
48+ for (int i = 0 ; i < n; ++i) sa[i] = sa[i + 1 ] - 1 ;
49+ for (int i = 0 ; i < n; ++i) rk[i] = rk[i + 1 ] - 1 ;
50+ if (n == 1 ) rk[0 ] = 0 ;
51+ for (int i = 0 ; i < n; ++i) height[i] = height[i + 1 ];
52+ }
53+
54+ template <typename T>
55+ class SparseTable {
56+ using VT = vector<T>;
57+ using VVT = vector<VT>;
58+ using func_type = function<T(const T &, const T &)>;
59+
60+ VVT ST;
61+
62+ static T default_func (const T &t1, const T &t2) { return min (t1, t2); }
63+
64+ func_type op;
65+
66+ public:
67+ SparseTable (const vector<T> &v, func_type _func = default_func) {
68+ op = _func;
69+ int len = v.size (), l1 = ceil (log2 (len)) + 1 ;
70+ ST.assign (len, VT (l1, 0 ));
71+ for (int i = 0 ; i < len; ++i) {
72+ ST[i][0 ] = v[i];
73+ }
74+ for (int j = 1 ; j < l1; ++j) {
75+ int pj = 1 << (j - 1 );
76+ for (int i = 0 ; i + pj < len; ++i) {
77+ ST[i][j] = op (ST[i][j - 1 ], ST[i + pj][j - 1 ]);
78+ }
79+ }
80+ }
81+
82+ T query (int l, int r) {
83+ int lt = r - l + 1 ;
84+ int q = floor (log2 (lt));
85+ return op (ST[l][q], ST[r - (1 << q) + 1 ][q]);
86+ }
87+ };
88+
89+ int pre_sum (vector<int > &pre , int l, int r) {
90+ if (l) return pre [r] - pre [l - 1 ];
91+ return pre [r];
92+ }
93+
94+ void solve () {
95+ int n, q;
96+ cin >> n >> q;
97+
98+ string s;
99+ cin >> s;
100+ pre = vector<int >(n, s[0 ] == ' 1' );
101+ for (int i = 1 ; i < n; ++i) {
102+ pre [i] = pre [i - 1 ] + (s[i] - ' 0' );
103+ }
104+ getsa (s);
105+ SparseTable<int > st (height);
106+
107+ while (q--) {
108+ int p, l, r;
109+ cin >> p >> l >> r;
110+ p--;
111+ l--;
112+ r--;
113+
114+ int lp = rk[p], rp = n;
115+ // 找 [p:l] 的左右端点
116+ int len = l - p + 1 ;
117+ while (lp + 1 != rp) {
118+ int mp = (lp + rp) >> 1 ;
119+ int lcp = 0 ;
120+ if (sa[mp] + len - 1 >= n) {
121+ rp = mp;
122+ continue ;
123+ }
124+ lcp = st.query (rk[p] + 1 , mp);
125+ if (lcp >= len) lp = mp;
126+ else rp = mp;
127+ }
128+ int R = lp;
129+
130+ lp = -1 , rp = rk[p];
131+ len = l - p + 1 ;
132+ while (lp + 1 != rp) {
133+ int mp = (lp + rp) >> 1 ;
134+ int lcp = 0 ;
135+ if (sa[mp] + len - 1 >= n) {
136+ lp = mp;
137+ continue ;
138+ }
139+ lcp = st.query (mp + 1 , rk[p]);
140+ if (lcp >= len) rp = mp;
141+ else lp = mp;
142+ }
143+ int L = rp;
144+
145+ lp = L, rp = R;
146+ ll ans = 0 ;
147+ for (int j = l; j <= r; ++j) {
148+ int len = j - p + 1 ;
149+ while (lp < n && sa[lp] + len - 1 > n || s[sa[lp] + len - 1 ] != s[j]) { lp++; }
150+ while (rp < n && sa[rp] + len - 1 > n || s[sa[rp] + len - 1 ] != s[j]) { rp--; }
151+ if (lp > rp) break ;
152+ ans += (rp - lp + 1 ) * pre_sum (pre , p, j);
153+ }
154+ cout << ans << endl;
155+ }
156+ }
157+
158+ signed main () {
159+ ios::sync_with_stdio (false );
160+ cin.tie (nullptr );
161+
162+ int t = 1 ;
163+ // cin >> t;
164+ while (t--) solve ();
165+ return 0 ;
166+ }
167+ /*
168+ 降维打击【算法赛】
169+ */
0 commit comments