题目大意:给你一个字符串,求其中本质不同的字串的个数 题解:同[洛谷P4070][SDOI2016]生成魔咒,只要最后再输出就行了 卡点:无 C++ Code: #include <cstdio> #include <map> #define maxn 100010 long long ans; namespace SAM { #define N (maxn << 1) #define root 1 int R[N], fail[N]; int nxt[N][26];…
题目链接https://www.luogu.org/problemnew/show/P2408 SAM裸题,大力求就行了 #include<cstdio> #include<cstring> typedef long long ll; const int maxn = 2e5+20; int par[maxn],mx[maxn],tr[maxn][26]; int cnt=1,last=1; void extend(int x) { int np = ++cnt,p=last; m…
## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样.子串的定义:原字符串中连续的一段字符组成的字符串 很妙的一道题,考察了对 $Height$ 数组的理解. $1.$首先,不难发现任意子串都可以被字符串中后缀串的前缀表达出来 $2.$我们知道, $Height[i]$ 被定义为排名为 $i$ 的后缀串与排名为 $i-1$ 的后缀串的 $LCP$. 而与排名为 $i$ 得后…
P2408 不同子串个数 计算一个字符串的不同子串个数 两种方法,一种是\(dp\)出来\(SAM\)从起点开始的路径数量 另一种方法就是计算每个点的\(len[i]-len[link[i]]\)这个计算的就是这个等价类的不同串的数量 //#pragma GCC optimize("O3") //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h>…
题目传送门 不同字串个数 题目背景 因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题: 题目描述 给你一个长为N的字符串,求不同的子串的个数 我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样. 子串的定义:原字符串中连续的一段字符组成的字符串 输入输出格式 输入格式: 第一行一个整数N 接下来一行N个字符表示给出的字符串 输出格式: 一行一个整数,表示不一样的子串个数 输入输出样例 输入样例#1: 5 aabaa 输出样例#1: 1…
次元传送门:洛谷P2679 思路 蒟蒻一开始并没有思路而去看了题解 我们发现对于两个字串的位置 我们只需要管他们匹配成功或者匹配失败即可 f[i][j][k] 记录当前 a[i]不论等不等于b[j] 我们可以选用也可以不选用 使用k个子串方案数(因为题目没有要求一定位置相同) r[i][j][k] 记录当前 a[i]==b[j] 并且我们选用a[i]和b[j] 方案数 使用k个子串方案数 状态转移方程: if(A[i]==B[j]) r[i][j][k]=(f[i-][j-][k-]+r[i-]…
LOJ 题面传送门 / 洛谷题面传送门 题意: 求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^md(ij)\),\(d(x)\) 为 \(x\) 的约数个数. \(n,m \leq 5 \times 10^4\). 抛出一个引理:\(d(ij)=\sum\limits_{x|i}\sum\limits_{y|j}[\gcd(x,y)=1]\),该定理将在这篇博客结束证明. 知道这个定理之后,就可以按照套路开始推式子了: \[\begin{aligned}&an…
题目链接 裸体就是身体. 建出\(SAM\),\(DAG\)上跑\(DP\),\(f[u]=1+\sum_{(u,v)\in DAG}f[v]\) 答案为\(f[1]-1\)(因为根节点没有字符) #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1000010; struct SAM{ int ch[26]; int len,…
一看完这道题就知道是划分型dp 有两个点要注意 (1)怎么预处理子串. 表示以i为开头,结尾在j之前(含),有没有子串,有就1,没有就0 (2)dp的过程 这种分成k组最优的题目已经高度模板化了,我总结一下吧 //f[i][j]表示把前j个数分成i组的最优价值 memset(f, 0xc0, sizeof(f)); //初始化 f[0][0] = 0; //不要忘记了 _for(k, 1, K) //枚举组数 _for(i, 1, len) //前i个字符 _for(j, 1, i) //断点…
考虑反向操作,去计算有多少组相同的子串,对于一组大小为k的极大相同子串的集合,ans-=k-1. 为了避免重复计算,需要一种有效的,有顺序的记录方案. 比如说,对于每一个相同组,按其起始点所在的位置排序,对于除了第一个串以外的串,均记-1的贡献. 但这种东西是非常难以快速统计的. 但是,可以对于每一个相同组,按其所在的后缀字典序排序,对于除了第一个串以外的串,均记-1的贡献. 下面引用别人的一段话,主要是利用lcp来快速统计了不用长度相同组. ==========================…