topic
LOJ2720 PSloj data better at.
LuoguP4770
each given two strings S and T, the first interrogation of a number of different sub-string string is not a second substrings.
Each query will give a different S, and T is a substring of a string start input (input \ ([l, r] \ ) described).
\ (| S |, | T | <= 5 \ times10 ^ 5, \ sum | S | <= 10 ^ 6 \)
Thinking
Data structure, ideology
- Segment tree merger (persistable)
Suffix automata
True ideas
- Several conventions statement: endpos represents the end position of the substring suffix automaton node represents, len indicates the length of the longest sub-string of the node represents, link represents a suffix link.
- First, to simplify the problem: Consider for each prefix string S, can determine how much the longest matched string T. Shorter than this would certainly not. Longer than this length, it is possible to re-use ParentTree. (Length only get yourself this node, the rest get on that node suffix link points)
- Tidy, we found that we ran on the string S as long as the matching length T suffix automaton, then the match length suffix automaton S placed on the number of different sub-strings ran.
- For example, the node 4 len is 8, link point No. 3, No. 3, len is the length of the matching node is 4,4 number 3. That can match length number 3 is also 3. In answer to No. 4 by 4, add 1 answer at No. 3. (Because there may be other nodes point 3, so we can not directly count 4)
- Then consider how to answer multiple sets of questions.
- We found that the problem lies in the S on T matching the length of the run this step. Because you will spot built SAM T out.
- So we consider the use of SAM total input string beginning to achieve matching.
- When we matched when a node (matched \ (CNT \) bits), the length of the real match, the node is in endpos [l, R & lt] this range, farthest from the endpos l to l, distance, and \ (CNT \) take \ (min \) results.
Ever since, we have to maintain it endpos collection. This can be combined with the tree line. But note that, when we should have been merged to create a new point (can be persistent), or else will destroy previously quite good endpos collection.
Little attention
- When we calculate the length of the match, if the current point \ ([l, r] \ ) distance l in the rightmost endpos to, than his small link in len, then we should jump to the link. As this may gain new endpos, more in the right place.
Sand sculpture of lojAC after cross Luogu, find RE. Finally, this should not have proved to be a function return values, the authors write int, but at the same time, there is no return, resulting in the valley do not give too upright Luo.Code
#include<bits/stdc++.h>
#define LL long long
#define MAXN 500000
using namespace std;
template<typename T>void Read(T &cn)
{
char c;int sig = 1;
while(!isdigit(c = getchar()))if(c == '-')sig = -1; cn = c-48;
while(isdigit(c = getchar()))cn = cn*10+c-48; cn*=sig;
}
template<typename T>void Write(T cn)
{
if(cn<0) {putchar('-'); cn = 0-cn; }
int wei = 0; T cm = 0; int cx = cn%10; cn/=10;
while(cn)wei++,cm = cm*10+cn%10,cn/=10;
while(wei--)putchar(cm%10+48),cm/=10;
putchar(cx+48);
}
int he[MAXN+1],xu[MAXN*2+1];
struct Seg{
struct node{
int ls,rs,da;
void qing() {ls = rs = da = 0; }
};
node t[MAXN*60+1];
int tlen;
int ro[MAXN*2+1];
void build() {tlen = 0; t[0].qing(); }
void jia(int &cn,int cm,int l,int r)
{
if(!cn)t[cn = ++tlen].qing();
if(l == r) {t[cn].da = cm; return; }
int zh = (l+r)>>1;
if(cm <= zh)jia(t[cn].ls,cm,l,zh); else jia(t[cn].rs,cm,zh+1,r);
t[cn].da = max(t[t[cn].ls].da,t[t[cn].rs].da);
}
int cha(int cn,int cm,int l,int r)
{
if(!cn)return 0;
if(r <= cm)return t[cn].da;
int zh = (l+r)>>1;
if(cm > zh)return max(cha(t[cn].rs,cm,zh+1,r),t[t[cn].ls].da);
else return cha(t[cn].ls,cm,l,zh);
}
void bing(int &cn,int cm1,int cm2,int l,int r)
{
if(!cm1 && !cm2)return;
if(!cm1) {cn = cm2; return; }
if(!cm2) {cn = cm1; return; }
cn = ++tlen;
t[cn].da = max(t[cm1].da,t[cm2].da);
if(l == r)return;
bing(t[cn].ls,t[cm1].ls,t[cm2].ls,l,(l+r)>>1);
bing(t[cn].rs,t[cm1].rs,t[cm2].rs,((l+r)>>1)+1,r);
}
}T;
struct SAM{
struct node{
int link,len,ch[26];
int edp,f;
void qing() {link = len = 0; memset(ch,0,sizeof(ch)); }
};
node t[MAXN*2+1];
int tlen,last;
void build() {t[tlen = last = 1].qing(); }
void jia(int cn,int cm)
{
int cur = ++tlen;
t[cur].qing();
t[cur].edp = cm;
t[cur].len = t[last].len+1;
int p = last;
for(;p && !t[p].ch[cn];p = t[p].link)t[p].ch[cn] = cur;
if(!p)t[cur].link = 1;
else{
int q = t[p].ch[cn];
if(t[p].len +1 == t[q].len)t[cur].link = q;
else{
int cln = ++tlen;
t[cln] = t[q]; t[cln].edp = 0;
t[cln].len = t[p].len+1;
t[cur].link = t[q].link = cln;
for(;p && t[p].ch[cn] == q;p = t[p].link)t[p].ch[cn] = cln;
}
}
last = cur;
}
void pro_edp()
{
T.build();
for(int i = 0;i<=t[last].len;i++)he[i] = 0;
for(int i = 1;i<=tlen;i++)he[t[i].len]++;
for(int i = 1;i<=t[last].len;i++)he[i] += he[i-1];
for(int i = 1;i<=tlen;i++)xu[he[t[i].len]--] = i;
for(int i = tlen;i>=1;i--)
{
if(t[xu[i]].edp)T.jia(T.ro[xu[i]],t[xu[i]].edp,1,t[last].len);
if(t[xu[i]].link)T.bing(T.ro[t[xu[i]].link],T.ro[t[xu[i]].link],T.ro[xu[i]],1,t[last].len);
}
}
int tongji(int n,int l,int r,int ans[],char c[])
{
int dang = 1,xian = 0;
for(int i = 1;i<=n;i++)
{
int lin = t[dang].ch[c[i]-'a'],lin2;
while(dang != 1 && (!lin || T.cha(T.ro[lin],r,1,t[last].len) < l))dang = t[dang].link,lin = t[dang].ch[c[i]-'a'],xian = min(xian,t[dang].len);
if(lin && T.cha(T.ro[lin],r,1,t[last].len) >= l)dang = lin,xian++; lin2 = T.cha(T.ro[dang],r,1,t[last].len);
while(dang != 1 && t[t[dang].link].len >= lin2 - l+1)dang = t[dang].link,xian = t[dang].len,lin2 = T.cha(T.ro[dang],r,1,t[last].len);
ans[i] = min(xian,lin2-l+1);
}
}
LL jisuan(int a[])
{
for(int i = 0;i<=t[last].len;i++)he[i] = 0;
for(int i = 1;i<=tlen;i++)he[t[i].len]++,t[i].f = 0;
for(int i = 1;i<=t[last].len;i++)he[i] += he[i-1];
for(int i = 1;i<=tlen;i++)xu[he[t[i].len]--] = i;
LL guo = 0;
for(int i = tlen;i>=1;i--)
{
if(t[xu[i]].edp)t[xu[i]].f = max(a[t[xu[i]].edp],t[xu[i]].f);
t[xu[i]].f = min(t[xu[i]].f,t[xu[i]].len);
guo = guo + t[xu[i]].len - max(t[xu[i]].f,t[t[xu[i]].link].len);
t[t[xu[i]].link].f = max(t[t[xu[i]].link].f,t[xu[i]].f);
}
return guo;
}
}S1,S2;
int clen,dlen;
char c[MAXN*2+1],d[MAXN*2+1];
int a[MAXN*2+1];
int n;
void getit(char c[],int &n)
{
while(!isalpha(c[1] = getchar())); n = 1;
while(isalpha(c[++n] = getchar())); n--;
}
int main()
{
// freopen("name1.in","r",stdin);
// freopen("name1.out","w",stdout);
getit(c,clen); S1.build();
for(int i = 1;i<=clen;i++)S1.jia(c[i]-'a',i); S1.pro_edp();
Read(n);
while(n--)
{
getit(d,dlen); int bx,by; Read(bx); Read(by);
S1.tongji(dlen,bx,by,a,d);
S2.build(); for(int i = 1;i<=dlen;i++)S2.jia(d[i]-'a',i);
Write(S2.jisuan(a)); putchar('\n');
}
return 0;
}