「HAOI2018」字串覆盖

题意:

​ 给你两个字符串,长度都为\(N\),以及一个参数\(K\),有\(M\)个询问,每次给你一个\(B\)串的一个子串,问用这个字串去覆盖\(A\)串一段区间的最大收益是多少?(\(N,M\le100000,K\leq10^9\))其中,子串长度在\(51\)到\(2000\)的询问个数不会超过\(11000\)个。

题解:

​ 题目的暗示很明显,分类做。

​ 建出\(sam\),维护\(right\)集。

​ 对于询问大于\(50\)的直接暴力跳。

​ 对于询问小于等于\(50\)的倍增跳。

​ 没了。

​ 本来不想写这篇博客,但是,我调这个题调了很久,为什么呢?我这记录一个神秘\(RE\)的地方。

  1. int merge(int x,int y)
  2. {
  3. if(!x&&!y)return 0;
  4. int o=++cnt;
  5. if(!x||!y)return tr[o]=tr[x^y],o;
  6. tr[o].ls=merge(tr[x].ls,tr[y].ls);
  7. tr[o].rs=merge(tr[x].rs,tr[y].rs);
  8. tr[o].siz=tr[tr[o].ls].siz+tr[tr[o].rs].siz;
  9. return o;
  10. }

​ 改成直接\(return \ x \ xor \ y\),就好了。gdb出来发现并不是爆数组,而是爆栈???有没有大佬可以教一下。

  1. #include<bits/stdc++.h>
  2. #define fo(i,l,r) for(int i=l;i<=r;i++)
  3. #define of(i,l,r) for(int i=l;i>=r;i--)
  4. #define fe(i,u) for(int i=head[u];i;i=e[i].next)
  5. #define el putchar('\n')
  6. #define ta putchar(' ')
  7. using namespace std;
  8. typedef long long ll;
  9. typedef pair<int,int> pii;
  10. inline void open(const char *s)
  11. {
  12. #ifndef ONLINE_JUDGE
  13. char str[20];
  14. sprintf(str,"%s.in",s);
  15. freopen(str,"r",stdin);
  16. sprintf(str,"%s.out",s);
  17. freopen(str,"w",stdout);
  18. #endif
  19. }
  20. inline int rd()
  21. {
  22. static int x,f;
  23. x=0;f=1;
  24. char ch=getchar();
  25. for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
  26. for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
  27. return f>0?x:-x;
  28. }
  29. const int N=100010,B=27;
  30. const int Ha1=998244353;
  31. const int Ha2=1000000007;
  32. int n,K,m,rt[N<<1];
  33. char s1[N],s2[N];
  34. int ps[N],pl[N];
  35. int h1[N],h2[N],bin1[N],bin2[N];
  36. ll ans[N];
  37. map<pii,int>mp;
  38. struct node{int s,t,l,r,L,id;}q[N];
  39. inline bool cmp(node a,node b){return a.L<b.L;}
  40. ll f[20][N],g[20][N],h[20][N];
  41. namespace Seg{
  42. #define lson tr[o].ls,l,mid
  43. #define rson tr[o].rs,mid+1,r
  44. #define qlson lson,L,min(mid,R)
  45. #define qrson rson,max(mid+1,L),R
  46. struct tree{
  47. int ls,rs,siz;
  48. tree(){ls=rs=siz=0;}
  49. }tr[N*40];int cnt=0;
  50. void insert(int &o,int l,int r,int x)
  51. {
  52. tr[++cnt]=tr[o];o=cnt;++tr[o].siz;
  53. if(l==r)return;int mid=(l+r)>>1;
  54. if(x<=mid)insert(lson,x);else insert(rson,x);
  55. }
  56. int query(int o,int l,int r,int L,int R)
  57. {if(L>R)return -1;
  58. if(!tr[o].siz)return -1;
  59. if(l==r)return l;
  60. int mid=(l+r)>>1;
  61. if(l==L&&r==R){
  62. if(tr[tr[o].ls].siz)return query(qlson);
  63. return query(qrson);
  64. }
  65. int res=-1;
  66. if(L<=mid)res=query(qlson);
  67. if(~res)return res;
  68. if(R>mid)res=query(qrson);
  69. return res;
  70. }
  71. int merge(int x,int y)
  72. {
  73. if(!x||!y)return x^y;
  74. int o=++cnt;
  75. tr[o].ls=merge(tr[x].ls,tr[y].ls);
  76. tr[o].rs=merge(tr[x].rs,tr[y].rs);
  77. tr[o].siz=tr[tr[o].ls].siz+tr[tr[o].rs].siz;
  78. return o;
  79. }
  80. }
  81. namespace Sam{
  82. int cnt=1,las=1,len[N<<1],fa[20][N<<1],ch[N<<1][26];
  83. inline int insert(int x)
  84. {
  85. int p=las,np=las=++cnt;len[np]=len[p]+1;
  86. for(;p&&!ch[p][x];p=fa[0][p])ch[p][x]=np;
  87. if(!p)return fa[0][np]=1,np;
  88. int q=ch[p][x];if(len[q]==len[p]+1)return fa[0][np]=q,np;
  89. int nq=++cnt;len[nq]=len[p]+1;fa[0][nq]=fa[0][q];fa[0][q]=fa[0][np]=nq;
  90. memcpy(ch[nq],ch[q],104);for(;p&&ch[p][x]==q;p=fa[0][p])ch[p][x]=nq;
  91. return np;
  92. }
  93. inline void build()
  94. {static int c[N<<1],pos[N<<1];
  95. fo(i,1,16)fo(j,2,cnt)fa[i][j]=fa[i-1][fa[i-1][j]];
  96. fo(i,1,cnt)++c[len[i]];
  97. fo(i,1,cnt)c[i]+=c[i-1];
  98. of(i,cnt,1)pos[c[len[i]]--]=i;
  99. of(i,cnt,2){
  100. int x=pos[i];
  101. rt[fa[0][x]]=Seg::merge(rt[fa[0][x]],rt[x]);
  102. }
  103. }
  104. inline void gao()
  105. {
  106. int o=1,l=0;
  107. fo(i,1,n){
  108. if(ch[o][s2[i]-'a'])++l,o=ch[o][s2[i]-'a'];
  109. else{
  110. for(;o&&!ch[o][s2[i]-'a'];o=fa[0][o]);
  111. if(!o)o=1,l=0;else l=len[o]+1,o=ch[o][s2[i]-'a'];
  112. }
  113. ps[i]=o;pl[i]=l;
  114. }
  115. }
  116. inline int jump(int x,int L){of(i,16,0)if(len[fa[i][x]]>=L)x=fa[i][x];return x;}
  117. }
  118. inline void inithsh()
  119. {
  120. bin1[0]=bin2[0]=1;
  121. fo(i,1,n)bin1[i]=1ll*B*bin1[i-1]%Ha1,bin2[i]=1ll*B*bin2[i-1]%Ha2;
  122. fo(i,1,n)h1[i]=(1ll*h1[i-1]*B%Ha1+s1[i]-'a')%Ha1;
  123. fo(i,1,n)h2[i]=(1ll*h2[i-1]*B%Ha2+s1[i]-'a')%Ha2;
  124. }
  125. inline pii gethsh(int l,int r){return pii((h1[r]-1ll*h1[l-1]*bin1[r-l+1]%Ha1+Ha1)%Ha1,(h2[r]-1ll*h2[l-1]*bin2[r-l+1]%Ha2+Ha2)%Ha2);}
  126. inline void init(int L)
  127. {
  128. mp.clear();
  129. fo(i,0,16)f[i][n+1]=n+1;
  130. of(i,n,L){
  131. pii hh=gethsh(i-L+1,i);
  132. if(mp.count(hh))f[0][i]=mp[hh];else f[0][i]=n+1;
  133. g[0][i]=i;h[0][i]=1;
  134. fo(j,1,16){
  135. f[j][i]=f[j-1][f[j-1][i]];
  136. g[j][i]=g[j-1][i]+g[j-1][f[j-1][i]];
  137. h[j][i]=h[j-1][i]+h[j-1][f[j-1][i]];
  138. }
  139. if(i+L-1<=n)mp[gethsh(i,i+L-1)]=i+L-1;
  140. }
  141. }
  142. inline ll gao1(int s,int t,int l,int r,int L)
  143. {
  144. int p=Sam::jump(ps[r],L);
  145. l=s;r=t;
  146. int x=Seg::query(rt[p],1,n,l+L-1,r);
  147. if(!~x)return 0;
  148. ll hh0=0,hh1=0;
  149. of(i,16,0)if(f[i][x]<=r)hh1+=g[i][x],hh0+=h[i][x],x=f[i][x];
  150. hh1+=x;++hh0;return hh0*K-hh1+hh0*(L-1);
  151. }
  152. inline ll gao2(int s,int t,int l,int r,int L)
  153. {
  154. int p=Sam::jump(ps[r],L);
  155. l=s;r=t;
  156. int x=Seg::query(rt[p],1,n,l+L-1,r);
  157. if(!~x)return 0;
  158. ll hh1=0,hh0=0;
  159. while(~x){
  160. hh1+=x;++hh0;
  161. x=Seg::query(rt[p],1,n,x+L,r);
  162. }
  163. return hh0*K-hh1+hh0*(L-1);
  164. }
  165. int main()
  166. {open("hh");
  167. n=rd();K=rd();
  168. scanf("%s",s1+1);scanf("%s",s2+1);
  169. fo(i,1,n)Seg::insert(rt[Sam::insert(s1[i]-'a')],1,n,i);
  170. Sam::build();Sam::gao();
  171. inithsh();
  172. m=rd();
  173. fo(i,1,m){
  174. int s=rd(),t=rd(),l=rd(),r=rd();
  175. q[i]=node{s,t,l,r,r-l+1,i};
  176. }
  177. sort(q+1,q+m+1,cmp);
  178. int pre=0;
  179. fo(i,1,m){
  180. if(pl[q[i].r]<q[i].L||q[i].t-q[i].s+1<q[i].L)continue;
  181. if(q[i].L<=50){
  182. if(q[i].L!=pre)init(q[i].L);
  183. ans[q[i].id]=gao1(q[i].s,q[i].t,q[i].l,q[i].r,q[i].L);
  184. }
  185. else ans[q[i].id]=gao2(q[i].s,q[i].t,q[i].l,q[i].r,q[i].L);
  186. pre=q[i].L;
  187. }
  188. fo(i,1,m)printf("%lld\n",ans[i]);
  189. return 0;
  190. }

时间复杂度:\(O(50Q\log N)\)

「HAOI2018」字串覆盖的更多相关文章

  1. 【LOJ】#2525. 「HAOI2018」字串覆盖

    题解 写后缀树真是一写就好久,然后调好久QAQ 我们把两个串取反拼一起建后缀树,这样的话使得后缀树是正串的后缀树 然后我们把询问挂在每个节点上,每次线段树合并,对于大于50的每次暴力跳着在线段树找,对 ...

  2. 「NOIP2002」「Codevs1099」 字串变换(BFS

    1099 字串变换 2002年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold   题目描述 Description 已知有两个字串 $A$, ...

  3. 【BZOJ5304】[HAOI2018]字串覆盖(后缀数组,主席树,倍增)

    [BZOJ5304][HAOI2018]字串覆盖(后缀数组,主席树,倍增) 题面 BZOJ 洛谷 题解 贪心的想法是从左往右,能选就选.这个显然是正确的. 题目的数据范围很好的说明了要对于询问分开进行 ...

  4. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  5. loj#2128. 「HAOI2015」数字串拆分 矩阵乘法

    目录 题目链接 题解 代码 题目链接 loj#2128. 「HAOI2015」数字串拆分 题解 \(f(s)\)对于\(f(i) = \sum_{j = i - m}^{i - 1}f(j)\) 这个 ...

  6. BZOJ5304 : [Haoi2018]字串覆盖

    离线处理所有询问. 对于$r-l\leq 50$的情况: 按照串长从$1$到$51$分别把所有子串按照第一位字符为第一关键字,上一次排序结果为第二关键字进行$O(n)$基数排序. 同理也可以用上一次比 ...

  7. 洛谷P4493 [HAOI2018]字串覆盖(后缀自动机+线段树+倍增)

    题面 传送门 题解 字符串就硬是要和数据结构结合在一起么--\(loj\)上\(rk1\)好像码了\(10k\)的样子-- 我们设\(L=r-l+1\) 首先可以发现对于\(T\)串一定是从左到右,能 ...

  8. LOJ #2527 Luogu P4491「HAOI2018」染色

    好像网上没人....和我推出....同一个式子啊..... LOJ #2527 Luogu P4491 题意 $ n$个格子中每个格子可以涂$ m$种颜色中的一种 若有$ k$种颜色恰好涂了$ s$格 ...

  9. 【LOJ】#2527. 「HAOI2018」染色

    题解 简单容斥题 至少选了\(k\)个颜色恰好出现\(S\)次方案数是 \(F[k] = \binom{M}{k} \frac{N!}{(S!)^{k}(N - i * S)!}(M - k)^{N ...

随机推荐

  1. bzoj1090 字符串折叠

    问题描述 折叠的定义如下: 1. 一个字符串可以看成它自身的折叠.记作S  S 2. X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S)  SSSS…S(X个S). 3. 如果A ...

  2. 转移顺序的艺术 luogu4394 + lougu2966 + luogu3537

    lougu4394: N个政党要组成一个联合内阁,每个党都有自己的席位数. 现在希望你找出一种方案,你选中的党的席位数要大于总数的一半,并且联合内阁的席位数越多越好. 对于一个联合内阁,如果某个政党退 ...

  3. 人在IT,关于计算机专业的杂谈PPT

  4. HNU 12961 BitTorrent DP

    题意: 你在网上下载东西,一个文件存储在一段或者多段里面,问怎么选择能在规定的流量内下载最多的文件数量.每段的大小一样. 思路: 习惯了做答案保存在DP数组里的题,做这种答案保存在下标里的题,转不过弯 ...

  5. [Python] Slice the data with pandas

    For example we have dataframe like this: SPY AAPL IBM GOOG GLD 2017-01-03 222.073914 114.311760 160. ...

  6. C++对象模型——效率有了,弹性呢(第七章)

    7.4    效率有了,弹性呢 传统的C++对象模型提供有效率的运行期支持.这份效率,再加上与C之间的兼容性,造成了C++的广泛被接受度.然而,在某些领域方面,像是动态共享函数库(dynamicall ...

  7. sass02

    新建一个文件夹 1 cd 进入文件夹 ,cd E:\360data\重要数据\桌面\sass, 2 compass creat hello:当前目录创建sass工程, 3 sass文件夹放置sass文 ...

  8. 1.MVC概要与angular概要、模板与数据绑定

    转自:https://www.cnblogs.com/best/p/6242011.html#_label3_0_8_2 一.前端MVC概要 1.1.库与框架的区别 1.2.AMD与CMD 1.2.前 ...

  9. Restricted Boltzmann Machines

    转自:http://deeplearning.net/tutorial/rbm.html http://blog.csdn.net/mytestmy/article/details/9150213 能 ...

  10. Oracle 审计初步使用

    新增一个表空间用于存储审计日志 SQL> CREATE tablespace audit_data datafile '/data/oradata/orcl/audit01.dbf' SIZE ...