首页 > 其他分享 >LOJ 6041 事情的相似度 题解

LOJ 6041 事情的相似度 题解

时间:2024-10-07 09:11:32浏览次数:7  
标签:SAM LOJ 题解 rep pos len int 6041 qry

Statement

先把串 reverse,多次给 \(l,r\),求

\[ \max_{l\le i<j\le r}\{\text{LCP}(i,j)\} \]

Solution

  • \(\text{sqrtlog}\sim\text{sqrt}\):莫队 + 线段树 / 树状数组 / set,用 SA 做
  • \(nm/\omega\):bitset 乱搞
  • \(\log^2\):SAM + LCT + BIT

在 parent 树上,LCP 等于 LCA 的 len

离线,每次加入右端点就 access 一下,过程中对产生的 LCA 关系进行更新.

  • 还有一种做法是在 parent 树上 set 启发式合并,然后二维数点

Code

一遍写完一遍过!太牛了。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;
const int N = 2e5 + 10;
vector<pair<int, int>> Queries[N];
int n, m;
string s;

struct BIT {
	int len, mx[N];
	BIT(int _len = 0) {
		len = _len, memset(mx, 0, sizeof(mx));
	}
	void Upd(int x, int v) {
		for (; x <= len; x += x & -x) mx[x] = max(mx[x], v);
	}
	int Qry(int x) {
		int res = 0;
		for (; x; x -= x & -x) res = max(res, mx[x]);
		return res;
	}
} bit;

namespace SAM {
	int sz, cur, last, len[N], link[N], nxt[N][2];
	void init() {
		link[0] = -1;
	}
	void extend(int ch) {
		cur = ++sz, len[cur] = len[last] + 1;
		int p = last;
		for (; ~p; p = link[p])
			if (!nxt[p][ch]) nxt[p][ch] = cur;
			else break;
		if (!~p) {
			link[cur] = 0;
		} else {
			int q = nxt[p][ch];
			if (len[p] + 1 == len[q]) {
				link[cur] = q;
			} else {
				int copy = ++sz;
				link[copy] = link[q], link[q] = link[cur] = copy, len[copy] = len[p] + 1;
				nxt[copy][0] = nxt[q][0], nxt[copy][1] = nxt[q][1];
				for (; ~p; p = link[p])
					if (nxt[p][ch] == q) nxt[p][ch] = copy;
					else break;
			}
		}
		last = cur;
	}
	void Build() {
		init();
		for (auto ch : s) extend(ch - 48);
		bit = BIT(n);
	}
}

int now;

namespace LinkCutTree {
	int fa[N], ch[N][2], tag[N], val[N];
  #define get(u) (u == ch[fa[u]][1])
  #define nrt(u) (u == ch[fa[u]][0] || u == ch[fa[u]][1])
	void cov(int u, int v) {
		if (u) tag[u] = val[u] = v;
	}
	void down(int u) {
		if (tag[u]) cov(ch[u][0], tag[u]), cov(ch[u][1], tag[u]), tag[u] = 0;
	}
	void Down(int u) {
		if (nrt(u)) Down(fa[u]);
		down(u);
	}
	void rot(int u) {
		int f = fa[u], g = fa[f], k = get(u);
		if (nrt(f)) ch[g][get(f)] = u;
		ch[f][k] = ch[u][!k];
		if (ch[u][!k]) fa[ch[u][!k]] = f;
		ch[u][!k] = f, fa[f] = u, fa[u] = g;
	}
	void splay(int u) {
		for (Down(u); nrt(u); rot(u)) if (nrt(fa[u])) rot(get(u) == get(fa[u]) ? fa[u] : u);
	}
	void access(int u) {
		int v = 0;
		for (; u; v = u, u = fa[u]) {
			splay(u);
			if (v) {
				bit.Upd(n - val[u] + 1, SAM::len[u - 1]);
			}
			ch[u][1] = v;
		}
		cov(v, now);
	}
  #undef get
  #undef nrt
}
int ans[N];

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	cin >> n >> m >> s;
	rep(i, 1, m) {
		int l, r;
		cin >> l >> r;
		Queries[r].push_back(make_pair(l, i));
	}
	SAM::Build();
	rep(i, 1, SAM::sz) LinkCutTree::fa[i + 1] = SAM::link[i] + 1;
	int pos = 0;
	rep(i, 1, n) {
		now = i;
		pos = SAM::nxt[pos][s[i - 1] - 48];
		LinkCutTree::access(pos + 1);
		for (auto qry : Queries[i])
			ans[qry.second] = bit.Qry(n - qry.first + 1);
	}
	rep(i, 1, m) {
		cout << ans[i] << '\n';
	}
	return 0;
}

标签:SAM,LOJ,题解,rep,pos,len,int,6041,qry
From: https://www.cnblogs.com/laijinyi/p/18449761

相关文章

  • P3332 K大数查询 题解
    Solution整体二分板子题vector太好写了111#include<bits/stdc++.h>usingnamespacestd;#definerep(i,j,k)for(inti=(j);i<=(k);++i)#definereo(i,j,k)for(inti=(j);i>=(k);--i)typedeflonglongll;constintN=50010;intn,m,ans[......
  • P4093 序列 题解
    Statement给出\(n\) 个数的序列\(\{a_i\}\),接下来\(m\)秒中每一秒会有一个数发生变化,然后恢复。问最长的子序列长度,使得任意时刻这个子序列不下降。\(n\le10^5\)Solution设\(b_i\)为\(i\)最小能变成的数,\(c_i\)为\(i\)最大能变成的数\[f(i)=\max_{j<i\landc......
  • P4690 镜中的昆虫 (动态区间颜色数) 题解
    Statement区间涂颜色区间颜色数Solution\(O(\text{polysqrt})\)略。\(O(\text{polylog})\)颜色段均摊有两层含义:随机数据下:任意时刻的颜色段个数期望\(O(\logn)\)非随机数据下:每次推平时访问的颜色段个数均摊\(O(n)\)首先维护每个点\(i\)的\(pre_i\),一次询......
  • Codeforces Rund 977 div2 个人题解(A~E1)
    CodeforcesRund977div2个人题解(A,B,C1,C2,E1)Dashboard-CodeforcesRound977(Div.2,basedonCOMPFEST16-FinalRound)-Codeforces火车头#define_CRT_SECURE_NO_WARNINGS1#include<algorithm>#include<array>#include<bitset>#includ......
  • 【题解】C - STEP
    目录题目内容DescriptionInputOutput数据规模与约定做法一思路代码做法2思路代码题目内容原题:洛谷P6492Description给定一个长度为\(n\)的字符序列\(a\),初始时序列中全部都是字符L。有\(q\)次修改,每次给定一个\(x\),若\(a_x\)为L,则将\(a_x\)修改成R,否则将\(a_x\)......
  • 常见问题解决 --- maven手动安装依赖jar包报错
    报错内容:执行命令mvninstall:install-file-DgroupId=com.beidouapp-DartifactId=SSDK-Dversion=4.0.2.0 -Dfile=C:\1\SSDK-Release-4.0.2.0.jar-Dpackaging=jar报错Unknownlifecyclephase“.ggstar“.Youmustspecifyavalidlifecyclephaseoragoal原因:在pow......
  • CCF-CSP认证资格考试题解系列——第4次第2题数字排序
    #include<iostream>#include<algorithm>usingnamespacestd;structre{ intvalue;//数值 intnum;//次数}re[1010];boolcmp(structrea,structreb){ if(a.num==b.num)returna.value<b.value;//次数相同是小的优先 returna.num>b.num;//次数不相同是次数优......
  • CCF-CSP认证资格考试题解系列——第4次第3题节日
    #include<iostream>usingnamespacestd;intm[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};intis_run(intyear){ if(year%400==0||(year%4==0&&year%100))return1; return0;}intgetdays(intyear,intmonth){ if(month==2)returnm[month]+i......
  • ABC374 E 题解
    ABC374E题解E-SensorOptimizationDilemma2题目链接:AT|洛谷容易发现答案可以二分。于是我们把问题转化为了判定性问题:给定目标\(x\),能否在花费不超过预算的情况下,使得每个过程的产量都不低于\(x\)?进一步,由于各个过程的生产互不相关,所以我们要尽可能让每个过程的费......
  • P7078 [CSP-S2020] 贪吃蛇 题解
    P7078[CSP-S2020]贪吃蛇这题好啊题目传送门看到题之后觉得有点像砍蚯蚓的那道题看看题目可以证明,若一条蛇在吃完之后不是最弱的那一条蛇,那么他一定会选择吃,证明如下设蛇长为\(a_{1,\dots,n}\)且依次递增,那么很明显的因为​......