BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)
题面
自己找去
HINT
给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种。我的思路是建立一个广义后缀自动机,对于每个节点记录\(size[1]和size[2]\)分别表示这个节点接受的子串在A中出现多少次,在B中出现多少次,然后\(ans=\sum_{u=2}^{tot}{size[u][1]*size[u][2]*(node[u].len-node[fa].len)}\)注意要long long
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
w=(w<<3)+(w<<1)+ch-48;
ch=getchar();
}
return w*f;
}
int n,m;
int size[800010][3];
struct SUFFIXAUTOMATON{
struct Node{
int fa,len;
map<int,int> ch;
}node[800010];
int lst,tot,root;
inline void init(){
lst=tot=root=1;return;
}
inline void extend(int now,int id){
int p=lst;tot++;lst=tot;int np=tot;
node[np].len=node[p].len+1;size[np][id]=1;
while(p&&!node[p].ch[now]){
node[p].ch[now]=np;
p=node[p].fa;
}
if(!p) node[np].fa=1;
else{
int q=node[p].ch[now];
if(node[q].len==node[p].len+1){
node[np].fa=q;
}
else{
int nq=++tot;node[nq]=node[q];
node[nq].len=node[p].len+1;
node[q].fa=nq;node[np].fa=nq;
while(p&&node[p].ch[now]==q){
node[p].ch[now]=nq;
p=node[p].fa;
}
}
}
}
}SAM;
int cnt,head[800010];
struct Edge{
int from,to,next;
}edge[1600010];
inline void addedge(int u,int v){
cnt++;
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
char ch[200010];
inline void dfs(int u){
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;dfs(v);
size[u][1]+=(long long)size[v][1];
size[u][2]+=(long long)size[v][2];
}
return;
}
long long ans;
signed main(){
SAM.init();
for(int i=1;i<=2;i++){
cin>>ch;int len=strlen(ch);
for(int j=0;j<len;j++){
SAM.extend(ch[j]-'a'+1,i);
}
SAM.lst=1;
}
for(int i=2;i<=SAM.tot;i++){
addedge(SAM.node[i].fa,i);
}
dfs(1);
//cout<<SAM.tot<<endl;
for(int i=2;i<=SAM.tot;i++){
int f=SAM.node[i].fa;
//cout<<(long long)size[i][1]*size[i][2]<<" "<<SAM.node[i].len-SAM.node[f].len<<endl;
long long cur1=(long long)size[i][1]*size[i][2];long long cur2=(long long)SAM.node[i].len-SAM.node[f].len;
//cout<<cur1<<" "<<cur2<<endl;
ans+=(long long)cur1*cur2;
}
cout<<ans<<endl;
return 0;
}
BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)的更多相关文章
- [HAOI2016]找相同字符 广义后缀自动机_统计出现次数
题目描述:给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 输入输出格式输入格式:两行,两个字符串 s1,s2,长度分别为n ...
- bzoj 4566 找相同字符 —— 广义后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4566 建出两个串的广义后缀自动机: 统计每个点在两个串中出现次数的子树和,其实就是在两个串中 ...
- 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】找相同字符(后缀自动机)
[BZOJ4566]找相同字符(后缀自动机) 题面 BZOJ 题解 看到多串处理,\(SA\)就连起来 \(SAM???\) 单串建自动机 然后其他串匹配 对于一个串建完\(SAM\)后 另一个串在\ ...
- BZOJ_4566_[Haoi2016]找相同字符_后缀自动机
BZOJ_4566_[Haoi2016]找相同字符_后缀自动机 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有 ...
- 【BZOJ4566】找相同字符【后缀自动机】
题意 给定两个字符串,求两个字符串相同子串的方案数. 分析 那么将字符串s1建SAM,然后对于s2的每个前缀,都在SAM中找出来,并且计数就行. 我一开始的做法是,建一个u和len,顺着s2跑SAM, ...
- BZOJ4566 HAOI2016找相同字符(后缀自动机)
对第一个串建SAM,第二个串在上面跑,记录当前前缀匹配的最长后缀长度l,每次考虑当前前缀的贡献,对于当前所在节点显然是|right|*(l-len[fa]),而对于其parent树上所有祖先的贡献显然 ...
- POJ3294Life Forms(广义后缀自动机)(后缀数组+二分+数状数组)
You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial ...
随机推荐
- 使用Git和Svn
一. 使用SVN 1. 下载tortoiseSVN 2. 右键SVN checkout(下载项目到本地) 3. 更新和提交 二. 使用GIT 1. 下载git 2. 下载tortoiseGit 3. ...
- 如何分析和研究Log文件 ,如何看日志信息
如何分析和研究Log文件 ,如何看日志信息 . Log 在android中的地位非常重要,要是作为一个android程序员不能过分析log这关,算是android没有入门吧 . 下面我们就来说说如何处 ...
- 1163 - Bank Robbery
1163 - Bank Robbery In one very cold morning, Mark decides to rob a bank. But while trying hacking ...
- WinBox软路由的自定义IP设定
软路由ros(MIKRTIK)安装简单步骤 由于本主也是刚刚接触软路由这个硬件方面的知识.所以也是略知皮毛而已,今天通过网上的学习,然后自己总结了一下怎么在软路由中设定一个自定义IP ...
- Hibernate入门之命名策略(naming strategy)详解
前言 JPA和Hibernate都提供了默认映射策略,通过映射将每个实体类映射到具有相同名称的数据库表,它的每个属性都映射到具有相同属性的列, 但是,在实际项目开发中可能出现与默认命名约定不匹配,也就 ...
- scrapy的useragent与代理ip
scrapy中的useragent与代理ip 方法一: user-agent我们可以直接在settings.py中更改,如下图,这样修改比较简单,但是并不推荐,更推荐的方法是修改使用scrapy的中间 ...
- C#建立自己的测试用例系统
引言 很多时候,需要对类中的方法进行一些测试,来判断是否能按要求输出预期的结果. C#提供了快速创建单元测试的方法,但单元测试不仅速度慢不方便,大量的单元测试还会拖慢项目的启动速度. 所以决定自己搞个 ...
- 多线程共享变量和 AsyncLocal
>>返回<C# 并发编程> 1. 简介 2. 异步下的共享变量 3. 解析 AsyncLocal 3.1. IAsyncLocalValueMap 的实现 3.2. 结论 1. ...
- golang单元测试简述
Golang中内置了对单元测试的支持,不需要像Java一样引入第三方Jar才能进行测试,下面将分别介绍Golang所支持的几种测试: 一.测试类型 Golang中单元测试有功能测试.基准测试. ...
- 11种常用css样式之border学习
边框border通常简写为"border:1px solid red;"但其实一个完整的border边框其实是由1.border-width/*边框宽度*/,2.border-st ...