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. [小问题笔记(十)] SQL Server 里 float 转 varchar等字符类型 不使用科学计数法

    需要转换两次, 试了一下 float 转 bigint 转 varchar 溢出了... 后来用  float 转 decimal(38,0) 转 varchar 就成功了~ ,)) )) 另吐槽一下 ...

  2. C#错误的面试题

    你面试的时候是不是碰到这样的问题 String s = new String("xyz");创建了几个String Object? ,对于这个问题,我之前也一直以为是对的,这样写是 ...

  3. Git出现fatal: Unable to find remote helper for 'https'

    使用Git远程获取代码 git clone https://github.com/twlkyao/findfile.git 出现“fatal: Unable to find remote helper ...

  4. 一、nginx 安装

    添加官方 yum 源 vim /etc/yum.repos.d/nginx.rep 输入以下内容(OS为你的系统,OSRELEASE 系统版本) [nginx] name=nginx repo bas ...

  5. [Mybatis]Spring与Mybatis整合的MapperScannerConfigurer处理过程源码分析

    转自:https://www.cnblogs.com/fangjian0423/p/spring-mybatis-MapperScannerConfigurer-analysis.html Mappe ...

  6. JS触发服务器控件的单击事件

    <script src="../Js/jquery-1.4.2.min.js" type="text/javascript"></script ...

  7. 搞懂分布式技术5:Zookeeper的配置与集群管理实战

    搞懂分布式技术5:Zookeeper的配置与集群管理实战 4.1 配置文件 ZooKeeper安装好之后,在安装目录的conf文件夹下可以找到一个名为“zoo_sample.cfg”的文件,是ZooK ...

  8. day7-python类反射

    一.概述 一般的高阶语言都有反射的功能特性,python也不例外,网上资料显示,python支持类反射和模块反射,今天就先学习一下类反射的相关知识,模块反射后续再展开把.Python的类反射用于把字符 ...

  9. 【Python MySQLdb】Library not loaded: /usr/local/mysql/lib/libmysqlclient.20.dylib解决办法

    使用MySQLdb遇到以下错误 ImportError: dlopen(/Users/jackey/Documents/Xiaomi/Code/wda_python/lib/python2./site ...

  10. 自研发RPC调用框架

    自主研发设计RPC远程调用框架,实现服务自动注册,服务发现,远程RPC调用,后续实现服务负载均衡 主要包括:客户端服务,服务端,服务发现,服务注册 github地址:https://github.co ...