BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】
Description
给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。
Input
两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母
Output
输出一个整数表示答案
Sample Input
aabb
bbaa
Sample Output
10
可以说是模板了
因为只有两个串,所以完全没有必要建trie
直接分别添加,在每个串开始添加之前让last=root就可以了
然后在extend上面加上已经有转移的特判
注意要后缀自动机建完之后再添加right标记
不然会出问题
//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define for_up(a, b, c) for (int a = b; a <= c; ++a)
#define for_down(a, b, c) for (int a = b; a >= c; --a)
#define for_vector(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x){
bool w = 1;x = 0;
char c = getchar();
while(!isdigit(c) && c != '-')c = getchar();
if(c == '-')w = 0, c = getchar();
while(isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if(!w)x=-x;
}
template <typename T>
void Write(T x){
if(x < 0) {
putchar('-');
x=-x;
}
if(x > 9)Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
const int CHARSET_SIZE = 26;
const int N = 4e5 + 10;
struct Sam {
Sam *ch[CHARSET_SIZE], *prt;
int maxl, right[2];
Sam (int maxl = 0):ch(),prt(NULL),maxl(maxl){
right[0] = right[1] = 0;
}
}pool[N<<1],*cur = pool, *root = new (cur++)Sam, *last = root;
int buc[N];
vector<Sam*> topo;
ll ans = 0;
void extend(int c){
if (last->ch[c] && last->maxl + 1 == last->ch[c]->maxl) {
last = last->ch[c];
return;
}
Sam *u = new (cur++)Sam(last->maxl + 1), *v = last;
for (; v && !v->ch[c]; v = v->prt) v->ch[c] = u;
if (!v) {
u->prt = root;
} else if (v->maxl + 1 == v->ch[c]->maxl) {
u->prt = v->ch[c];
} else {
Sam *n = new (cur++)Sam(v->maxl + 1), *o = v->ch[c];
copy(o->ch, o->ch + CHARSET_SIZE, n->ch);
n->prt = o->prt;
o->prt = u->prt = n;
for (; v && v->ch[c] == o;v = v->prt) v->ch[c] = n;
}
last = u;
}
void toposort(){
int maxv = 0;
for (Sam *p = pool; p != cur; ++p){
maxv = max(maxv, p->maxl);
buc[p->maxl]++;
}
for_up(i, 1, maxv) buc[i] += buc[i-1];
topo.resize(cur-pool);
for (Sam *p = pool; p != cur; ++p)topo[--buc[p->maxl]] = p;
for_down(i, topo.size()-1, 1) {
Sam *p = topo[i];
p->prt->right[0] += p->right[0];
p->prt->right[1] += p->right[1];
ans += 1ll * (p->maxl - p->prt->maxl) * p->right[0] * p->right[1];
}
}
char c[2][N];
int main() {
scanf("%s",c[0] + 1);
int len0 = strlen(c[0] + 1);
for_up(i, 1, len0) extend(c[0][i]-'a');
last = root;
scanf("%s",c[1] + 1);
int len1 = strlen(c[1] + 1);
for_up(i, 1, len1) extend(c[1][i]-'a');
Sam *now = root;
for_up(i, 1, len0) {
now = now->ch[c[0][i]-'a'];
now->right[0] = 1;
}
now = root;
for_up(i, 1, len1) {
now = now->ch[c[1][i]-'a'];
now->right[1] = 1;
}
toposort();
Write(ans);
return 0;
}
BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】的更多相关文章
- [HAOI2016]找相同字符 广义后缀自动机_统计出现次数
题目描述:给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 输入输出格式输入格式:两行,两个字符串 s1,s2,长度分别为n ...
- BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机
建立广义后缀自动机. 然后统计子树中的siz,需要分开统计 然后对(l[i]-l[fa[i]])*siz[i][0]*siz[i][1]求和即可. #include <cstdio> #i ...
- bzoj 4566 [Haoi2016]找相同字符——广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 每个后缀结尾处 ct[ ] = 1 ,按拓扑序 dp 一下就能求出 right 集合的 ...
- BZOJ4566 HAOI2016找相同字符(后缀自动机)
对第一个串建SAM,第二个串在上面跑,记录当前前缀匹配的最长后缀长度l,每次考虑当前前缀的贡献,对于当前所在节点显然是|right|*(l-len[fa]),而对于其parent树上所有祖先的贡献显然 ...
- BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机) 题面 自己找去 HINT 给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种.我的思路 ...
- BZOJ_4566_[Haoi2016]找相同字符_后缀自动机
BZOJ_4566_[Haoi2016]找相同字符_后缀自动机 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有 ...
- 【BZOJ4566】找相同字符(后缀自动机)
[BZOJ4566]找相同字符(后缀自动机) 题面 BZOJ 题解 看到多串处理,\(SA\)就连起来 \(SAM???\) 单串建自动机 然后其他串匹配 对于一个串建完\(SAM\)后 另一个串在\ ...
- bzoj 4566 找相同字符 —— 广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 建出两个串的广义后缀自动机: 统计每个点在两个串中出现次数的子树和,其实就是在两个串中 ...
- 【BZOJ4566】找相同字符【后缀自动机】
题意 给定两个字符串,求两个字符串相同子串的方案数. 分析 那么将字符串s1建SAM,然后对于s2的每个前缀,都在SAM中找出来,并且计数就行. 我一开始的做法是,建一个u和len,顺着s2跑SAM, ...
- BZOJ4566 [Haoi2016]找相同字符 【后缀数组】
题目 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. 输入格式 两行,两个字符串s1,s2,长度分别为n1,n2.1 & ...
随机推荐
- Spring Cloud 坑点
1 配置中心 1.config 默认Git加载 通过spring.cloud.config.server.git.uri指定配置信息存储的git地址,比如:https://github.com/spr ...
- e.target和e.currentTarget区别
直接上代码: body里: <div id="father"> father <div id="son"> son </div&g ...
- vue下个兄弟节点
checkOne(e) { e.currentTarget.nextElementSibling.style.background = 'red' }
- js从一个select选择数据添加到另一个select(包括移除)
一.实现效果 二.要求 1.选中左侧的菜单,点击“>>”,该菜单(1项或多项选中的)将添加到右侧菜单 2.选中右侧菜单,点击“<<”,则移除选中的菜单 3.点击“>> ...
- TIME_WAIT和CLOSE_WAIT
先看下三次握手四次挥手的状态变化: 通常会遇到下面两种情况: 服务器保持了大量TIME_WAIT状态 服务器保持了大量CLOSE_WAIT状态 因为linux分配给一个用户的文件句柄是有限的,而TIM ...
- iOS学习-字符串的删除替换
字符串的常用处理,删除,替换.记录一下,方便查找. -------------------------------------------------------------------------- ...
- 如何调试nRF5 SDK
本文将讲述Nordic nRF5 SDK的主要调试手段,以帮助大家快速定位问题,并解决问题.一般来说,你可以通过打log方式,IDE的debug模式,SDK自带的app_error_check函数,以 ...
- 毕业设计总结(1)-canvas画图
去年6月底完成的毕业设计,到现在也才开始给它做个总结,里面有很多可以学习和借鉴的东西. 我的毕业设计的题目是“一种路径规划算法的改进与设计”,具体的要求可参见下面的表格: 题目 一种路径规划算法的改进 ...
- kindeditor支持flv视频播放方法
打开plugins\media下面的media.js,打开,找到下面的代码: var html = K.mediaImg(self.themesPath + ‘common/blank.gif’, { ...
- [转]通过rsync+inotify-tools+ssh实现触发式远程实时同步
文件的同步镜像在很多地方都需要用到,因此rsync这款免费软件得到了广泛的应用,包括在Windows平台上,都已经有了支持rsync的“cwRsyncServer”. 但是,我们一般都是通过结合cro ...