[BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机
4556: [Tjoi2016&Heoi2016]字符串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1215 Solved: 484
[Submit][Status][Discuss]
Description
佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物。生日礼物放在一个神奇的箱子中。箱子外边写了
一个长为n的字符串s,和m个问题。佳媛姐姐必须正确回答这m个问题,才能打开箱子拿到礼物,升职加薪,出任CE
O,嫁给高富帅,走上人生巅峰。每个问题均有a,b,c,d四个参数,问你子串s[a..b]的所有子串和s[c..d]的最长公
共前缀的长度的最大值是多少?佳媛姐姐并不擅长做这样的问题,所以她向你求助,你该如何帮助她呢?
Input
输入的第一行有两个正整数n,m,分别表示字符串的长度和询问的个数。接下来一行是一个长为n的字符串。接下来
m行,每行有4个数a,b,c,d,表示询问s[a..b]的所有子串和s[c..d]的最长公共前缀的最大值。1<=n,m<=100,000,
字符串中仅有小写英文字母,a<=b,c<=d,1<=a,b,c,d<=n
Output
对于每一次询问,输出答案。
Sample Input
5 5
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4
aaaaa
1 1 1 5
1 5 1 1
2 3 2 3
2 4 2 3
2 3 2 4
Sample Output
1
1
2
2
2
1
2
2
2
HINT
Source
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<cstdio> 7 #define maxn 200010 8 using namespace std; 9 int n,m; 10 struct data { 11 int last,cnt; 12 int link[maxn],step[maxn],son[maxn][26]; 13 int v[maxn],pos[maxn],fa[maxn][20],w[maxn]; 14 int s[maxn*20][2],rt[maxn],t; 15 void insert(int &k,int l,int r,int x) { 16 k=++t; 17 if(l==r) return; 18 int mid=l+r>>1; 19 if(x<=mid) insert(s[k][0],l,mid,x); 20 else insert(s[k][1],mid+1,r,x); 21 } 22 int merge(int x,int y) { 23 if(!x||!y) return x+y; 24 int z=++t; 25 s[z][0]=merge(s[x][0],s[y][0]);s[z][1]=merge(s[x][1],s[y][1]); 26 return z; 27 } 28 bool query(int x,int l,int r,int L,int R) { 29 if(!x) return 0; 30 if(L<=l&&R>=r) return 1; 31 int mid=l+r>>1; 32 if (R<=mid) return query(s[x][0],l,mid,L,R); 33 else if(L>mid) return query(s[x][1],mid+1,r,L,R); 34 else return query(s[x][0],l,mid,L,mid)||query(s[x][1],mid+1,r,mid+1,R); 35 } 36 data() {last=cnt=1;} 37 void extend(int x,int id) { 38 int p=last,np=last=++cnt;step[np]=step[p]+1;insert(rt[np],1,n,id);w[id]=np; 39 while(p&&!son[p][x]) son[p][x]=np,p=link[p]; 40 if(!p) link[np]=1; 41 else { 42 int q=son[p][x]; 43 if(step[q]==step[p]+1) link[np]=q; 44 else { 45 int nq=++cnt; 46 memcpy(son[nq],son[q],sizeof(son[q])); 47 link[nq]=link[q]; 48 link[q]=link[np]=nq; 49 step[nq]=step[p]+1; 50 while(p&&son[p][x]==q) son[p][x]=nq,p=link[p]; 51 } 52 } 53 } 54 void pre() { 55 for(int i=1;i<=cnt;i++) v[step[i]]++; 56 for(int i=1;i<=cnt;i++) v[i]+=v[i-1]; 57 for(int i=cnt;i;i--) pos[v[step[i]]--]=i; 58 for(int i=cnt;i;i--) { 59 rt[link[pos[i]]]=merge(rt[link[pos[i]]],rt[pos[i]]); 60 fa[pos[i]][0]=link[pos[i]]; 61 } 62 for(int j=1;j<=18;j++) for(int i=1;i<=cnt;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; 63 } 64 bool check(int mid,int x,int l,int r) { 65 for(int i=18;i>=0;i--) if(step[fa[x][i]]>=mid) x=fa[x][i]; 66 return query(rt[x],1,n,l,r); 67 } 68 }a; 69 char ch[maxn]; 70 int main() { 71 scanf("%d%d",&n,&m); 72 scanf("%s",ch+1);reverse(ch+1,ch+n+1); 73 for(int i=1;i<=n;i++) a.extend(ch[i]-'a',i); 74 a.pre(); 75 for(int i=1;i<=m;i++) { 76 int a1,b1,c1,d1;scanf("%d%d%d%d",&a1,&b1,&c1,&d1); 77 a1=n-a1+1;b1=n-b1+1;c1=n-c1+1;d1=n-d1+1; 78 swap(a1,b1);swap(c1,d1); 79 int l=1,r=min(d1-c1+1,b1-a1+1); 80 while(l<=r) { 81 int mid=l+r>>1; 82 if(a.check(mid,a.w[d1],a1+mid-1,b1)) l=mid+1; 83 else r=mid-1; 84 } 85 printf("%d\n",l-1); 86 } 87 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~