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 找相同字符【广义后缀自动机】的更多相关文章

  1. [HAOI2016]找相同字符 广义后缀自动机_统计出现次数

    题目描述:给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 输入输出格式输入格式:两行,两个字符串 s1,s2,长度分别为n ...

  2. BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机

    建立广义后缀自动机. 然后统计子树中的siz,需要分开统计 然后对(l[i]-l[fa[i]])*siz[i][0]*siz[i][1]求和即可. #include <cstdio> #i ...

  3. bzoj 4566 [Haoi2016]找相同字符——广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 每个后缀结尾处 ct[ ] = 1 ,按拓扑序 dp 一下就能求出 right 集合的 ...

  4. BZOJ4566 HAOI2016找相同字符(后缀自动机)

    对第一个串建SAM,第二个串在上面跑,记录当前前缀匹配的最长后缀长度l,每次考虑当前前缀的贡献,对于当前所在节点显然是|right|*(l-len[fa]),而对于其parent树上所有祖先的贡献显然 ...

  5. BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)

    BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机) 题面 自己找去 HINT 给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种.我的思路 ...

  6. BZOJ_4566_[Haoi2016]找相同字符_后缀自动机

    BZOJ_4566_[Haoi2016]找相同字符_后缀自动机 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有 ...

  7. 【BZOJ4566】找相同字符(后缀自动机)

    [BZOJ4566]找相同字符(后缀自动机) 题面 BZOJ 题解 看到多串处理,\(SA\)就连起来 \(SAM???\) 单串建自动机 然后其他串匹配 对于一个串建完\(SAM\)后 另一个串在\ ...

  8. bzoj 4566 找相同字符 —— 广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 建出两个串的广义后缀自动机: 统计每个点在两个串中出现次数的子树和,其实就是在两个串中 ...

  9. 【BZOJ4566】找相同字符【后缀自动机】

    题意 给定两个字符串,求两个字符串相同子串的方案数. 分析 那么将字符串s1建SAM,然后对于s2的每个前缀,都在SAM中找出来,并且计数就行. 我一开始的做法是,建一个u和len,顺着s2跑SAM, ...

  10. BZOJ4566 [Haoi2016]找相同字符 【后缀数组】

    题目 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. 输入格式 两行,两个字符串s1,s2,长度分别为n1,n2.1 & ...

随机推荐

  1. Zookeeper Zkclient客户端

    Zkclient是对Zookeeper的原生API进行了包装,实现了超时重连.Watcher反复注册等功能,它可以实现递归创建,删除节点,但是zkClient不能递归给节点赋值. 主要的api如下: ...

  2. 关于IIS权限问题(Selenium WebDriver调用出错记录)

    本地VS调试过程中用Selenium WebDriver打开FF浏览器可以正常工作,项目部署至IIS后请求调用浏览器一直提示超时,异常如下: 因为本地调试可以成功,首先排除组件版本问题和浏览器兼容问题 ...

  3. RabbitMQ :常用命令与图形管理及用户权限

    RabbitMQ 安装 安装 RabbitMQ 前要先安装 Erlang,可以去 Erlang 官网下载,接着去 RabbitMQ 官网下载安装包,解压缩即可 Mac 用户可以通过 HomeBrew ...

  4. 数据库原理及应用-用户接口及SQL查询语言(Query Language)

    2018-02-07 20:41:39 一.DBMS的用户接口 查询语言 访问DBMS的访问工具(GUI) API 相关类库 二.SQL语言 SQL语言可以细分为四种: 1.Data Definiti ...

  5. ASP.NET Core and .NET Core Library Support

    ASP.NET Core and .NET Core Library Support 详情参见:https://github.com/linezero/NETCoreLibrary/blob/mast ...

  6. Nginx 启动报错 “/var/run/nginx/nginx.pid" failed”

    问题: 重启虚拟机后,再次重启nginx会报错: open() "/var/run/nginx/nginx.pid" failed (2: No such file or dire ...

  7. LeetCode 454. 4Sum II

    454. 4Sum II Add to List Description Submission Solutions Total Accepted: 8398 Total Submissions: 18 ...

  8. HDU-4123-树形dp+rmq+尺取

    Bob’s Race Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别

    JavaScript是一种解释型语言,函数声明会在JavaScript代码加载后.执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释. 在JS中有两种定义函数的方式, 1是:var aaa= ...

  10. Qt5.3中qml ApplicationWindow设置窗口无边框问题

    这个版本的qt在这里有点bug.. 设置ApplicationWindow的flags属性为Qt.FramelessWindowHint的确可以使程序无边框,但是同时程序在任务栏的图标也没了. 看文档 ...