bzoj 2865 字符串识别——后缀数组】的更多相关文章

集训讲字符串的时候我唯一想出正解的题-- 链接 BZOJ 2865 题面 给出一个长度为n (n <= 5e5) 的字符串,对于每一位,求包含该位的.最短的.在原串中只出现过一次的子串. 题解 "只出现过一次",想到后缀数组,后缀数组可以求出以第i位开头的最短的在原串中只出现过一次的子串--它的长度是min(height[rank[i]], height[rank[i] + 1) + 1. 所以我们枚举每个位置i,找到这个串,然后考虑它的贡献: 对于这个串之内的位置,答案可以用这…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2865 唯一出现的子串就是每个后缀除去和别的后缀最长的 LCP 之外的前缀: 所以用这个更新一段区间的答案,可以用线段树维护: 在 sa[i] ~ sa[i]+LCP+1 位置的答案由 LCP+1 更新,sa[i]+LCP+1 之后的位置就更新一个位置 ps 表示从 ps 到本位置的子串也可以: 最后两个取min即可: 注意如果整个后缀就是 LCP,那么就不能更新了: 线段树中 ps 的初值…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2865 做出 ht[ ] 之后,sa[ ] 上每个位置和它前面与后面取 LCP ,其中较大的长度设为 d ,表示从 sa[ i ] 位置开始的子串的右端点要在 sa[ i ]+d-1 位置之后才是只出现了一次的. 那么 sa[ i ] ~ sa[ i ]+d 位置的答案可以对 d+1 取 min :至于 sa[ i ]+d+1 ~ n 位置,sa[ i ]可能成为它们答案的开头位置,所以可以…
根据height数组的定义,和当前后缀串i最长的相同串的长度就是max(height[i],height[i+1]),这个后缀贡献的最短不同串长度就是len=max(height[i],height[i+1]) 考虑这个贡献的范围,对于i~i+len,贡献是len,对于w=i+len+1~n可以更新w-len+1,也就是这长为len的串再向右延伸,可以证明这也是不重子串 这两个东西用两个线段树维护,w-len+1这个直接把-len+1打在线段树上,查询的时候再加回w即可 #include<ios…
很容易想到只考虑后缀长度必须为\(max(height[rk[i]],height[rk[i]+1])+1\)(即\([i,i+x-1]\)代表的串只出现过一次)然后我正着做一遍反着做一遍,再取一个\(min\)最后挂了... 设\(x=max(height[rk[i]],height[rk[i]+1])+1\)我们考虑\(i\)的贡献,会给区间\([i,i+x-1]\)一个贡献x ,设\(r=i+x-1\)然后会给r+1一个贡献x+1就是(r+1)-i+1,接着是r+2的贡献(r+2)-i+1…
[BZOJ4556]字符串(后缀数组,主席树) 题面 BZOJ 题解 注意看题: 要求的是\([a,b]\)的子串和[c,d]的\(lcp\)的最大值 先来一下暴力吧 求出\(SA\)之后 暴力枚举\([A,B]\)之间的后缀 求一个\(lcp\) 复杂度\(O(nm)\) \(40\)分到手 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<…
[LOJ#3095][SNOI2019]字符串(后缀数组) 题面 LOJ 题解 首先画图看看如何比较两个串的大小,发现这个东西等价于求两个相邻的后缀的\(LCP\). 一个做法是求出\(SA\),然后就可以很容易的判断两个位置的大小了. 然而实际上相邻两个后缀的\(LCP\)转移可以很容易的从前一个得到,所以这部分的复杂度不会超过\(O(n)\). 那么复杂度瓶颈就在排序了,时间复杂度\(O(nlogn)\). #include<iostream> #include<cstdio>…
题意 一个长为 \(n\) 的字符串 \(s\),和 \(m\) 个询问.每次询问有 \(4\) 个参数分别为 \(a,b,c,d\). 要你告诉它 \(s[a...b]\) 中的所有子串 和 \(s[c...d]\) 的 最长公共前缀 \((\mathrm{LCP})\) 的最大值. \((1\le n,m\le 10^5, a\le b,c\le d,1\le a,b,c,d\le n)\) 题解 一开始看错了题 以为是 \([a,b]\) 中所有子串 和 \([c,d]\) 中所有子串的…
建一个广义后缀自动机(每加完一个串都返回root),在parent树上dpsum记录合法长度,打着时间戳往上跳,最后每个串在自动机上跑一变统计答案即可. 后缀数组理解起来可能方便一点,但是难写,就只说一下思路--把这些串加上特殊字符拼起来,然后按着sa扫,对每个位置二分长度,再左右端点(用height判断是否有k个) #include<iostream> #include<cstdio> #include<cstring> using namespace std; co…
题意 略 分析 考场上写了暴力建图40分溜了-(结果只得了30分) 然后只要优化建边就行了 首先给出的支配关系无法优化,就直接A向它支配的B连边. 考虑B向以B作为前缀的所有A连边,做一遍后缀数组,两个区间的左端点位置的LCP一定大于等于B的长度.在排好序的后缀数组上就是一段区间.然后用线段树优化建边. 那么用ST表倍增算一下能拓展的区间就行了. 然后由于只能向长度大于自己的连边,就按长度排序然后线段树改成主席树. 写+调一个下午-发现是sb错误- CODE #include <bits/std…
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过的,也就是考虑左端点在i.右端点在什么范围内时这个子串没有出现过--答案是右端点在[i + height[i] - 1, n]范围内时这个子串没出现过,即右端点在没有被"i与排在前一个的后缀的公共前缀"覆盖的部分时,这个子串没有出现过. 那么我们记录以每个i开头的新子串的数量,求前缀和,然…
3172: [Tjoi2013]单词 Time Limit: 10 Sec   Memory Limit: 512 MB Submit: 268   Solved: 145 [ Submit][ Status] Description 某人读论文,一篇论文是由许多单词组成.但他发现一个单词会在论文中出现很多次,现在想知道每个单词分别在论文  中出现多少次. Input 第一个一个整数N,表示有多少个单词,接下来N行每行一个单词.每个单词由小写字母组成,N<=200,单词长度不超过10^6 Out…
题意: 给出一个字符串,至多将其划分为n部分,每一部分取出字典序最大的子串ci,最小化 最大的ci 先看一个简化版的问题: 给一个串s,再给一个s的子串t,问能否通过将串划分为k个部分,使t成为划分后的s的字典序最大子串   对于这个问题,从串s的最后面开始,一个字符一个字符的向前推 如果当前[l,r]字典序比t大,那么[l+1,r]就要单独成为一段 比较子串字典序大小用二分+哈希 因为我们是一个字符一个字符的向前推的,所以一定是新的l使当前[l,r]字典序比t大 所以如果此时l==r,那么这个…
题目大意:给定一个n个单词的文章,求每一个单词在文章中的出现次数 文章长度<=10^6(不是单词长度<=10^6,不然读入直接超时) 首先将全部单词用空格连接成一个字符串.记录每一个单词的起始位置和长度 然后求后缀数组,对于每一个单词后缀数组中一定有连续一段后缀以这个单词开头,我们通过一開始记录的起始位置找到这个单词的后缀,然后左右端点二分答案,满足左右端点之间的后缀与原单词的LCP都当与等于原单词长度就可以 时间复杂度O(nlogn) #include<cstdio> #incl…
3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao Sample Output 54 HINT 2<=N<=500000,S由小写英文字母组成 Source 后缀数组+单调栈水过... #include<map> #include<cmath> #include<…
Time limit per test: 1.0 seconds Memory limit: 256 megabytes 子串的定义是在一个字符串中连续出现的一段字符.这里,我们使用 s[l…r] 来表示 s 字符串从 l 到 r(闭区间)的子串.在本题中,字符串下标从 0 开始.显然,对于长度为 n 的字符串共有 n(n+1)2 个子串. 对于一个给定的字符串 s,唐纳德给出 q 次询问,第 i 次询问包括三个参数 li,ri,zi,问在 s[li…ri] 的所有子串中共有多少个恰好为 zi.…
题目大意 给定后缀数组sa,要求构造出满足sa数组的字符串.或输出无解\(n\leq 5*10^5\) 题解 我们按照字典序来考虑每个后缀 对于\(Suffix(sa[i])\)和\(Suffix(sa[i-1])\) 我们一定知道\(Suffix(sa[i-1])<Suffix(sa[i])\). 如果我们有\(Suffix(sa[i-1]+1)<Suffix(sa[i]+1)\) 那么\(sa[i]\)和\(sa[i-1]\)两个位置上的字符相等时也满足条件 那么从贪心的角度来讲我们就让\…
题目的Source好有趣. 我们求出SA,然后求出每一个后缀中与前面本质不同的字符串的个数. 然后二分求出当前的字符串. 然后就是正反两次后缀数组求LCP的裸题了. 要注意,这时两个串的起点可能会相同,所以需要判掉. 无论读入还是输出都有可能爆long long,要注意 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace s…
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 居然把后缀数组写成n^2的..我真厉害.. 想了无数种方法,最后发现就是比后缀字典序排名,后缀数组即可 注意每个字符串的结尾处要加上一个\(\inf\), 因为相当于要把空位尽量后移使得非空位集中在前面 代码 #include<cstdio> #include<cstdlib> #include<cstring> #include<alg…
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in", "r", stdin) #define maxn 4000000 using namespace std; int n, m, tot; int arr[maxn], height[maxn], A[maxn]; namespace SA { int rk[maxn], tp[maxn], sa[maxn], tax[maxn]…
后缀数组 概念 实际上就是将一个字符串的所有后缀按照字典序排序 得到了两个数组 \(sa[i]\) 和 \(rk[i]\),其中 \(sa[i]\) 表示排名为 i 的后缀,\(rk[i]\) 表示后缀 i 的排名 注意到 \(rk\) 和 \(sa\) 是互逆的,即 \(sa[rk[i]]=rk[sa[i]]=i\) 先讨论几个关于 \(lcp\) 的性质,令 \(lcp(i,j)\) 表示 \(sa[i]\) 和 \(sa[j]\) 的最长公共前缀 \(lcp(l,r)=min(lcp(l,…
直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2007 Dec]队列变换 于是就hash后二分找相同的最长区间,然后比较后一个谁更小- 时间复杂度O(nlogn)O(nlogn)O(nlogn). 注意先在最后加一个极大值.因为如果一个序列A到末尾刚好与序列B的一段相等,那么一定是取B更优,因为B后面可能有更小的. hack数据 4 2 2 2…
[USACO07DEC]Best Cow Line G [USACO07DEC]Best Cow Line G 小声哔哔:字符串hash牛逼 题意 给出一个字符串,每次可以从字符串的首尾取出一个字符,放到队列的尾部,求可以得到的最小的字典序是多少? 思路1 此时字符串首尾的下标分别为l,r. 如果str[l]!=str[r]:取较小的字符串 如果str[l]==str[r]:找到第一个非负整数x,使得str[l+x]!=str[r-x]. ​ 如果str[l+x]<str[r-x],那么此时取s…
http://acm.hdu.edu.cn/showproblem.php?pid=1403 Longest Common Substring Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3068    Accepted Submission(s): 1087 Problem Description Given two string…
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAByIAAALuCAIAAABtq0bwAAAgAElEQVR4nOy9f2wb150vev4boESelngZLLpcraEneIWsqvL2inhXV4KvnwRDhsEFVyr8wnWhgRchlJXzxLcxt45QJmvGgFV3nIJ9jagbJn2Wk7KxoIhF5tZREivmVn66Ng1bMsprtnJ1TbsWA2fiRQeuwT/OH83O+2OGM2dmzgyHP2Q5zfeD…
后缀数组解法: 先二分最长前缀长度 \(len\),然后从 \(rnk[c]\) 向左右二分 \(l\) 和 \(r\) 使 \([l,r]\) 的 \(height\geq len\),然后在主席树上查 \(sa[l..r]\) 是否有 \(a..b\) 中的任意一个数.时间复杂度 \(O(n\log^2 n)\) \(Code\ Below:\) #include <bits/stdc++.h> using namespace std; const int maxn=100000+10;…
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3230 作出后缀数组,从 LCP 看每个位置对于本质不同子串的贡献,而且他们已经按前面部分排好序了,所以直接在 sa[ ] 上二分就能找到询问的子串. 找最长公共前缀就用 ht[ ] 和子串的长度比较就行.找最长公共后缀就一开始把原串翻转,做出翻转后的 ht[ ] ,就能查询了. 也可以二分一个最长公共后缀的位置,然后用正常的 ht[ ] 判断. 注意 long long . #includ…
传送门 解题思路 其实题目挺好想的.首先子串排名可以由后缀数组求得,因为不算重复的,所以后缀数组的每个后缀排名的去掉\(lcp\)的前缀排名为当前后缀的子串排名.这样就可以预处理出每个后缀的\(l,r\),查询的时候二分出来属于哪个后缀,用\(rmq\)求个\(lcp\).倒过来处理的式子比较麻烦,要先将排名转化成位置,然后找到对应的倒过来的位置,最后在转化为排名,具体看代码. 代码 #include<iostream> #include<cstdio> #include<c…
1396: 识别子串 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 312  Solved: 193[Submit][Status][Discuss] Description Input 一行,一个由小写字母组成的字符串S,长度不超过10^5 Output L行,每行一个整数,第i行的数据表示关于S的第i个元素的最短识别子串有多长. Sample Input agoodcookcooksgoodfood Sample Output 1 2 3 3…
Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一行n个整数,第i个整数表示第i个字符串的答案. Sample Input 3 1 abc a ab Sample Output 6 1 3 HINT 对于 100% 的数据,1<=n,k<=10^5,所有字符串总长不超过10^5,字符串只包含小写字母. 思路 首先发现这东西是真的不好做...那就找…