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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. POJ3294Life Forms(广义后缀自动机)(后缀数组+二分+数状数组)

    You may have wondered why most extraterrestrial life forms resemble humans, differing by superficial ...

随机推荐

  1. ELF和BIN的区别,资料整理

    https://www.cnblogs.com/fah936861121/articles/8143556.html 1.Bin Bin文件是最纯粹的二进制机器代码, 或者说是"顺序格式&q ...

  2. shell脚本 监控ps 不存在则重启

    监控 tomcat ,如果自动停止了,则重新启动 #!/bin/bash Start=/usr/local/apache-tomcat-8.0.24/bin/startup.sh Url=" ...

  3. mysql 启动,停止,重启

    启动mysql: 方式一:sudo /etc/init.d/mysql start  方式二:sudo start mysql 方式三:sudo service mysql start sudo ./ ...

  4. .gitignore配置规则

    1.gitignore文件 在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改 .gitignore 文件的方法.这个文件每一行保存了一个匹配的规则例如: # 此为注释 – 将被 ...

  5. C++中的多态及虚函数大总结

    多态是C++中很关键的一部分,在面向对象程序设计中的作用尤为突出,其含义是具有多种形式或形态的情形,简单来说,多态:向不同对象发送同一个消息,不同的对象在接收时会产生不同的行为.即用一个函数名可以调用 ...

  6. 学Python必背的初级单词,你都背了吗?

    今天给大家分享一些学习Python必须认识的英文单词,同时也是学习编程都必须会的单词,新手赶快学起来!有点长耐心看完. 小编推荐一个学Python的学习裙:九三七六六七 五零九,无论你是大牛还是小白, ...

  7. JavaScript之if流程控制演练,if写在区间内怎么解决

    什么是编程?通俗意见上来讲,就是把人的思维与步骤通过代码的形式书写展示出来,JavaScript的流程控制包含条件判断if,switch选择,循环for while:if(表达式 条件)=>真{ ...

  8. Android Binder实现浅析-Binder驱动

    简介 Android是如何实现跨进程通信的,大家熟悉的Binder是什么,怎么设计的,进程间的数据如何发送接收的.本文将以及解析,并对Binder驱动实现.Native层实现.Java层实现三块做一个 ...

  9. Android中实现自定义View组件并使其能跟随鼠标移动

    场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 新建An ...

  10. 何时使用异步或同步AJAX

    通常最好使用异步调用 通过优锐课核心java学习笔记中,我们可以看到,码了很多专业的相关知识, 分享给大家参考学习. AJAX代表异步JavaScript和XML,是一项允许异步更新网页的技术,这意味 ...