CF666E 题解

首先可以将所有的串用无关字符连接起来:s[1]+’#’+s[2]+’#’…s[n]

然后建一个SAM。

在每一个节点上搞一个动态开点线段树。

然后从下往上线段树合并。

最后像最长公共子串那样跑一边,倍增找到节点就可以了。

/*
{
######################
#       Author       #
#        Gary        #
#        2020        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXLEN=1e6+20;
struct state{int len,link,minlen,rt;unordered_map<char,int> ch;
};
int cnt=0;
vector<int> l(1,0),r(1,0);
vector<mp> ret(1,II(0,0));
mp get(mp A,mp B){if(A.SEC!=B.SEC){if(A.SEC<B.SEC) return B;return A;}return min(A,B);
}
int newnodes(){cnt++;ret.PB(II(0,0));l.PB(0);r.PB(0);return cnt;
}
const int N=1<<16;
void add(int now,int pos,int L=1,int R=N+1){if(L>pos||R<=pos) return;if(L==R-1){ret[now].FIR=L;ret[now].SEC++;return ;}int mid=(L+R)>>1;if(!l[now]){l[now]=newnodes();r[now]=newnodes();}add(l[now],pos,L,mid);add(r[now],pos,mid,R);ret[now]=get(ret[l[now]],ret[r[now]]);
}
int merge(int A,int B,int L=1,int R=N+1){if(A==0||B==0){return A+B; }if(L==R-1){newnodes();ret[cnt].FIR=L;ret[cnt].SEC=ret[A].SEC+ret[B].SEC; return cnt;}newnodes();int now=cnt;int mid=(L+R)>>1;l[now]=merge(l[A],l[B],L,mid);r[now]=merge(r[A],r[B],mid,R);ret[now]=get(ret[l[now]],ret[r[now]]);return now;
}
mp query(int a,int b,int now,int L=1,int R=N+1){if(!now) return II(0,0);if(R<=a||L>=b) return II(0,0);if(R<=b&&L>=a) {return ret[now];   }int mid=(L+R)>>1;return get(query(a,b,l[now],L,mid),query(a,b,r[now],mid,R));
}
struct SAM{ int sz=0,last;state st[MAXLEN+MAXLEN];bool vis[MAXLEN+MAXLEN];int siz[MAXLEN+MAXLEN];//出现次数 vector<int> g[MAXLEN+MAXLEN];int siz2[MAXLEN+MAXLEN];//状态大小 void sam_init(){memset(vis,0,sizeof(vis));st[0].len=0;st[0].link=-1;sz=0;st[0].rt=newnodes();last=0;}SAM(){sam_init();}void sam_extend(char c,int id){int cur=++sz;st[cur].rt=newnodes();st[cur].len=st[last].len+1;int p=last;while(p!=-1&&st[p].ch.find(c)==st[p].ch.end()){st[p].ch[c]=cur;p=st[p].link;} if(p==-1){st[cur].link=0;}else{int q=st[p].ch[c];if(st[q].len==st[p].len+1){st[cur].link=q;}else{int clone;clone=++sz;st[clone].rt=newnodes();st[clone].len=st[p].len+1;st[clone].ch=st[q].ch;st[clone].link=st[q].link;while(p!=-1&&st[p].ch.find(c)!=st[p].ch.end()&&st[p].ch[c]==q){st[p].ch[c]=clone;p=st[p].link;}st[cur].link=st[q].link=clone;}}last=cur;siz[cur]++;add(st[cur].rt,id);}void dfs(int now){vis[now]=true;for(auto it:g[now]){if(!vis[it]) dfs(it);siz[now]+=siz[it];}}void dfs2(int now){vis[now]=1;for(auto it:g[now]){if(!vis[it]) dfs2(it);siz2[now]+=siz2[it];}}void dfs3(int now){for(auto it:g[now]){dfs3(it);st[now].rt=merge(st[now].rt,st[it].rt);
//          cout<<now<<' '<<it<<' '<<' '<<ret[st[it].rt].FIR<<' '<<ret[st[it].rt].SEC<<")("<<ret[st[now].rt].SEC<<' '<<ret[st[now].rt].SEC<<endl;}}void run(){rb(i,1,sz) g[st[i].link].PB(i);rb(i,0,sz) if(!vis[i]) dfs(i);dfs3(0);rb(i,0,sz) g[i].clear();memset(vis,0,sizeof(vis));siz2[0]=1;rb(i,0,sz) for(auto ite=st[i].ch.begin();ite!=st[i].ch.end();ite++) g[ite->SEC].PB(i);rb(i,0,sz) if(!vis[i]) dfs2(i);rb(i,1,sz) st[i].minlen=st[i].len-siz2[i]+1;}
}sam;
int stay[500000+10];
int le[500000+10];
int bz[MAXLEN+MAXLEN][20];
int main(){//--------------------
//  int A=newnodes(),B=newnodes();
//  add(A,1);
//  add(B,1);
//  A=merge(A,B);
//  cout<<ret[A].SEC<<endl;
//  return 0;//--------------------string s;cin>>s;int m;cin>>m;rb(i,1,m){string t;cin>>t;sam.sam_extend('#',m+1);rep(j,t.length()){sam.sam_extend(t[j],i);}}sam.run();
//  cout<<sam.st[0].rt<<' '<<ret[sam.st[0].rt].SEC<<endl;int leng=s.length();int now=0,len=0;rb(i,1,leng){while(now!=-1&&sam.st[now].ch.find(s[i-1])==sam.st[now].ch.end()){now=sam.st[now].link;len=sam.st[now].len;}if(now==-1){now=0;len=0;}else{now=sam.st[now].ch[s[i-1]];len++;}stay[i]=now;le[i]=len;}rb(i,1,sam.sz){bz[i][0]=sam.st[i].link;}rb(j,1,19){rb(i,1,sam.sz){bz[i][j]=bz[bz[i][j-1]][j-1];       }}int q;scanf("%d",&q);rb(i,1,q){int l,r,pl,pr;scanf("%d%d%d%d",&l,&r,&pl,&pr);pl=pr-pl+1;if(le[pr]<pl){printf("%d 0\n",l);  continue;}int now=stay[pr];rl(i,19,0){if(sam.st[bz[now][i]].len>=pl){now=bz[now][i];}}now=sam.st[now].rt;mp rest=query(l,r+1,now);if(rest.SEC==0) rest.FIR=l;printf("%d %d\n",rest.FIR,rest.SEC);}return 0;
}

CF 666E 题解相关推荐

  1. CF 1742C 题解 P8557 炼金术(Alchemy) 题解

    温馨提示:\color{#E74C3C}\text{温馨提示:}温馨提示: 遇见题解勿抄袭,棕名封号两行泪.\color{#E74C3C}\text{遇见题解勿抄袭,棕名封号两行泪.}遇见题解勿抄袭, ...

  2. CF #717 题解

    CF #717 题解 A - Tit or Tat 贪心地从前面拿数,加到最后一位即可. B - AGAGA XOOORRR 转化一下,是求是否能把序列分成若干段( ≥ 2 \ge 2 ≥2),每段的 ...

  3. CF 1742C 题解

    温馨提示:\color{#E74C3C}\text{温馨提示:}温馨提示: 遇见题解勿抄袭,棕名封号两行泪.\color{#E74C3C}\text{遇见题解勿抄袭,棕名封号两行泪.}遇见题解勿抄袭, ...

  4. 【codeforces】【比赛题解】#915 Educational CF Round 36

    虽然最近打了很多场CF,也涨了很多分,但是好久没写CF的题解了. 前几次刚刚紫名的CF,太伤感情了,一下子就掉下来了,不懂你们Div.1. 珂学的那场我只做了第一题--悲伤. 这次的Education ...

  5. CF 742 B-Arpa’s obvious problem and Mehrdad’s terrible solution

    传送门 : CF 742B 题解 异或逆运算 AC code: /*adrui's submission Language : C++ Result : Accepted Lover : zyy Fa ...

  6. HZOJ 赤(CF739E Gosha is hunting)

    本来没有打算写题解的,时间有点紧.但是这个wqs二分看了好久才明白还是写点东西吧. 题解就直接粘dg的了: 赤(red) 本题来自codeforces 739E,加大了数据范围. 首先对一只猫不会扔两 ...

  7. Codeforces Round #368 (Div. 2)

    5/5 失踪多天发一下CF的题解,突然发现CF题解评论区一堆大神在晒解法,我等渣渣就顺手膜拜了一发,学了不少姿势,以后一打完CF就去评论区找姿势好了...... 最近有一个感悟,就是不要让别人告诉你一 ...

  8. CF76A·gift

    初见安~[第一次写CF的题解QwQ]这里是传送门:Codeforces 76A Description The kingdom of Olympia consists of N cities and  ...

  9. codeforces 186D Mushroom Scientists 不等式

    http://codeforces.com/blog/entry/4488 还是直接看cf的题解吧 am-gm不等式.. 又学到了 #include <iostream> #include ...

最新文章

  1. flex版的流程设计器
  2. 免费创办网站_足够好的工程来创办一家互联网公司
  3. 阿里云Redis集群版简要介绍
  4. python getattr调用自己模块_在Python中通过getattr获取对象引用的方法
  5. Mysql大型数量下的数据库构建的30条建议
  6. 从Config文件中读取节点的配置信息
  7. mysql安全权限的讲解
  8. SAP Spartacus 3.0部署在development environment上
  9. 中国信通院金融科技负责人韩涵:大数据是生产资料的变革,区块链是生产关系的变革...
  10. leetcode: 451. Sort Characters By Frequency
  11. mysql查询表中名字包含某个字符_查询当前数据库中所有用户表中哪些字段包含某个字符串...
  12. 提高(微)服务安全的非完全攻略
  13. 学习vim: 常用命令
  14. dx绘制2d图像_【3D建模】聊聊2D动画软件
  15. JUnit 单元测试多线程测试解决方法
  16. 前端50个精美登录注册模板(觉得好用帮我点个赞呗)
  17. 武汉大学计算机学院 工程硕士,武汉大学计算机学院在职人员攻读工程硕士学位招生专业介绍...
  18. 微信小程序一星期入门-完结篇--电影详情页的制作
  19. 音乐与计算机的论文题目,音乐类毕业论文选题参考
  20. 2020互联网大厂职级对应薪资一览表

热门文章

  1. 华雨欢:行情开启上行走势,区间突破指日可待
  2. PDF Editor 6 Pro for Mac(pdf编辑器)
  3. B. Combinatorics Homework(抽屉原理)
  4. flutter 阿里 号码认证_我对Flutter的第一次失望
  5. 针不戳 java后端开发岗面经分享,面经+知识点+总结
  6. 数字图像处理学习笔记-图像处理基础1
  7. 有趣之-图书管理系统
  8. 卡巴斯基2011 汉化增强版 KIS/KAV 11.0.1.400
  9. PX4-AutoPilot教程--搭建并运行第一个应用程序
  10. bootstrap手机网站H5模板固定底部顶部导航DEMO下载