Luogu P3181 [HAOI2016]找相同字符 广义$SAM$
题目链接 \(Click\) \(Here\)
设一个串\(s\)在\(A\)中出现\(cnt[s][1]\)次,在\(B\)中出现\(cnt[s][2]\)次,我们要求的就是:
$$\sum cnt[s][1]*cnt[s][2]$$
在\(SAM\)这种把多个串用一个点表示的东西里,答案就变成了这个
$$\sum cnt[s][1] * cnt[s][2] * (len[fa[s]]-len[s])$$
其中的\(cnt\)求法,听说好像可以两个串隔开求?但是我不太会。学了一下用广义\(SAM\)的写法,似乎是第一个串建完之后把\(las\)指针指回根节点,再建第二个就好。因为网上对于这种写法各种声音都有,所以我打算这周末认真学习\(SA\)和\(SAM\)后再详细进行解释说明或者算法更正。
\(p.s\)这种写法下似乎不能以\(len\)桶排序求\(cnt\),因为\(len\)会有相等情况。所以我们要用\(Parent\) \(Tree\)上\(DP\)来写。
最后提醒:别忘\(long\) \(long\)
#include <bits/stdc++.h>
using namespace std;
const int N = 800010;
typedef long long ll;
ll tot[2][N];
int node = 1, las = 1;
int fa[N], len[N], ch[N][26];
void extend (int c, int id) {
int p = las, q = ++node;
len[q] = len[p] + 1, tot[id][q] = 1, las = q;
while (p != 0 && ch[p][c] == 0) {
ch[p][c] = q;
p = fa[p];
}
if (p == 0) {
fa[q] = 1;
} else {
int x = ch[p][c];
if (len[x] == len[p] + 1) {
fa[q] = x;
} else {
int y = ++node;
len[y] = len[p] + 1;
fa[y] = fa[x];
fa[x] = fa[q] = y;
memcpy (ch[y], ch[x], sizeof (ch[x]));
while (p != 0 && ch[p][c] == x) {
ch[p][c] = y;
p = fa[p];
}
}
}
}
int cnt, head[N];
struct edge {
int nxt, to;
}e[N];
void add_edge (int from, int to) {
e[++cnt].nxt = head[from];
e[cnt].to = to;
head[from] = cnt;
}
void dfs (int u) {
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
dfs (v);
tot[0][u] += tot[0][v];
tot[1][u] += tot[1][v];
}
}
ll get_ans () {
ll ans = 0;
for (int i = 1; i <= node; ++i) add_edge (fa[i], i); dfs (1);
for (int i = 1; i <= node; ++i) ans += 1LL * (len[i] - len[fa[i]]) * tot[0][i] * tot[1][i];
return ans;
}
int n1, n2;
char s1[N], s2[N];
int main () {
scanf ("%s %s", s1, s2);
n1 = strlen (s1), n2 = strlen (s2);
for (int i = 0; i < n1; ++i) extend (s1[i] - 'a', 0);
las = 1;
for (int i = 0; i < n2; ++i) extend (s2[i] - 'a', 1);
cout << get_ans () << endl;
}
Luogu P3181 [HAOI2016]找相同字符 广义$SAM$的更多相关文章
- bzoj4566 / P3181 [HAOI2016]找相同字符
P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机. 我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...
- BZOJ4566 [Haoi2016]找相同字符 字符串 SAM
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4566.html 题目传送门 - BZOJ4566 题意 给定两个字符串 $s1$ 和 $s2$ ,问有 ...
- P3181 [HAOI2016]找相同字符
思路 广义SAM 把两个字符串建成广义SAM,然后统计两个SAM中相同节点的endpos大小乘积即可 记得开long long 代码 #include <cstdio> #include ...
- [洛谷P3181][HAOI2016]找相同字符
题目大意:给你两个字符串,求从两个字符串中各选择一个字串使得这两个字串相同的方案数. 题解:建广义$SAM$,对每个点求出在第一个串中出现次数和第二个串中出现次数,乘起来就行了 卡点:无 C++ Co ...
- BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 275 Solved: 155[Submit][Statu ...
- 【BZOJ4566】[HAOI2016]找相同字符
[BZOJ4566][HAOI2016]找相同字符 题面 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 其中\(1\le ...
- [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1212 Solved: 694[Submit][Stat ...
- 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈
[BZOJ4566][Haoi2016]找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同 ...
- bzoj 4566 [Haoi2016]找相同字符SA
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 128 Solved: 75[Submit][Status ...
随机推荐
- Eclipse报错:An internal error has occurred. Widget is disposed
win10家庭版报错. 右键Eclipse的快捷方式,在兼容性窗口的兼容模式中,将“以兼容模式运行这个程序”选项打对勾.选择win8就可以解决问题.
- Redis 禁用FLUSHALL FLUSHDB KEYS 命令
(error) ERR unknown command 'keys'问题解决(error) ERR unknown command 'FLUSHDB' 问题解决 背景 FLUSHALL FLUSH ...
- C# Web开发中弹出对话框的函数[转载]
public void Alert(string str_Message) { ClientScriptManager scriptManager =((Page)System.Web.HttpCon ...
- 学习 Spring (十五) Advisor
Spring入门篇 学习笔记 advisor 就像一个小的自包含的方面,只有一个 advice 切面自身通过一个 bean 表示,并且必须实现某个 advice 接口,同时 advisor 也可以很好 ...
- 【C/C++】递归算法
所谓递归——函数的递归调用.c语言的这种特性给程序设计带来许多方便.尤其是接触数据结构时,会发现递归的出现频率非常之高,也行之有效~下面是笔者在接触递归这个东西时的一些个人总结和体会: 1.直接或间接 ...
- 如何下载旧版本的MySQL
可能存在这样的场景,比如一些老系统需要使用MySQL 5.5版本才能运行,其余的不行. 1.登录下载站点 https://dev.mysql.com/downloads/mysql/ 此时的最新版本为 ...
- python 脚本之 获取远程主机的hostname
import sys, socket try: result = socket.gethostbyaddr("查询的IP") #查询完后获得一个元组 print (result) ...
- BZOJ3275Number——二分图最大权独立集
题目描述 有N个正整数,需要从中选出一些数,使这些数的和最大.若两个数a,b同时满足以下条件,则a,b不能同时被选1:存在正整数C,使a*a+b*b=c*c2:gcd(a,b)=1 输入 第一行一个正 ...
- Android学习第6天
创建一个新的activity 四大组件需要在清单文件中配置 可在清单文件中配置多个启动图标过单个启动图标 Activity下的lable和icon属性可以和Application节点的属性不一样,默认 ...
- win10系统同时安装python2.7和python3.6
我是先在本机上安装的python3.6.5,因为要学习一个框架,但是这个框架只支持python2,所以我又安装了python2.7.15,并且配置到系统环境变量 环境变量配置了python3.6.5的 ...