4566: [Haoi2016]找相同字符

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 275  Solved: 155
[Submit][Status][Discuss]

Description

给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两
个子串中有一个位置不同。

Input

两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母

Output

输出一个整数表示答案


一看两个串就是一个建SAM另一个跑

跑到状态s,贡献为|Right(s)|*(len-Min(s)+1)  也就是|Right(s)|*[len-Max(Parent(s))] 出现次数*不同串长度

并且出现次数向父亲传递,s的Parent Tree祖先也匹配了,贡献为|Right(v)|*[Max(v)-Min(v)+1]

于是我们先计算Right集合大小,然后跑的时候维护当前公共长度len,到一个状态实时更新自己(因为需要len),然后记录下访问次数,最后倒着递推用这些访问次数更新祖先就行了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=4e5+;
typedef long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,d[N];
char s[N];
struct State{
int ch[],par,val;
}t[N];
int sz,root,last;
inline int nw(int _){t[++sz].val=_;return sz;}
inline void iniSAM(){sz=;root=last=nw();}
void extend(int c){
int p=last,np=nw(t[p].val+); d[np]=;
for(;p&&!t[p].ch[c];p=t[p].par) t[p].ch[c]=np;
if(!p) t[np].par=root;
else{
int q=t[p].ch[c];
if(t[q].val==t[p].val+) t[np].par=q;
else{
int nq=nw(t[p].val+);
memcpy(t[nq].ch,t[q].ch,sizeof(t[q].ch));
t[nq].par=t[q].par;
t[q].par=t[np].par=nq;
for(;p&&t[p].ch[c]==q;p=t[p].par) t[p].ch[c]=nq;
}
}
last=np;
}
int c[N],a[N];
void RadixSort(){
for(int i=;i<=n;i++) c[i]=;
for(int i=;i<=sz;i++) c[t[i].val]++;
for(int i=;i<=n;i++) c[i]+=c[i-];
for(int i=sz;i>=;i--) a[c[t[i].val]--]=i;
}
int appear[N];
ll ans,f[N];
void solve(){
iniSAM();
scanf("%s",s+);n=strlen(s+);
for(int i=;i<=n;i++) extend(s[i]-'a'); RadixSort();
int u;
for(int i=sz;i>=;i--)
u=a[i],d[t[u].par]+=d[u]; int len=;u=root;
scanf("%s",s+);n=strlen(s+);
for(int i=;i<=n;i++){
int c=s[i]-'a';
if(t[u].ch[c]) len++,u=t[u].ch[c];
else{
while(u&&!t[u].ch[c]) u=t[u].par;
if(!u) u=root, len = 0;
else len=t[u].val+,u=t[u].ch[c];
}
appear[u]++,ans+=(ll)d[u]*(len-t[t[u].par].val);
}
for(int i=sz;i>=;i--)
u=a[i],f[t[u].par]+=f[u]+appear[u];
for(int i=;i<=sz;i++) ans+=(ll)d[i]*f[i]*(t[i].val-t[t[i].par].val);
printf("%lld",ans);
}
int main(){
freopen("in","r",stdin);
solve();
}

BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]的更多相关文章

  1. BZOJ.4566.[HAOI2016]找相同字符(后缀数组 单调栈)

    题目链接 给定两个字符串,求它们有多少个相同子串.相同串的位置不同算多个. POJ3145简化版. 后缀自动机做法见这儿,又快又好写(一下就看出差距了..) //13712kb 4076ms #inc ...

  2. [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1212  Solved: 694[Submit][Stat ...

  3. bzoj 4566 [Haoi2016]找相同字符SA

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 128  Solved: 75[Submit][Status ...

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

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

  5. ●BZOJ 4566 [Haoi2016]找相同字符

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4566题解: 广义后缀自动机 对两个串同时建立一个广义后缀自动机. 同时统计出每个状态对两个串 ...

  6. HAOI2016 找相同字符 后缀自动机

    两个串,考虑一建一跑.枚举模式串的位置\(i\),考虑每次统计以\(i\)结尾的所有符合要求的串.在后缀自动机上走时记录当前匹配长度\(curlen\),则当前节点的贡献是\((curlen-len[ ...

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

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

  8. bzoj 4566: [Haoi2016]找相同字符

    Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...

  9. BZOJ4566: [Haoi2016]找相同字符(后缀自动机)

    题意 题目链接 Sol 直接在SAM上乱搞 枚举前缀,用SAM统计可以匹配的后缀,具体在匹配的时候维护和当前节点能匹配的最大值 然后再把parent树上的点的贡献也统计上,这部分可以爆跳parent树 ...

随机推荐

  1. flume1.8 开发指南学习感悟

    概述: Apache Flume是一个分布式.可用的系统,用于从许多不同的sources有效的收集并移动大量日志数据用于集中存储数据. 架构及数据流动模型: flume实际上就是一个Agent.Age ...

  2. 关于数据库timestamp类型问题

    数据库使用timestamp类型字段,默人时间为0000-00-00 00:00:00 于是后台会报java.sql.SQLException: Value '0000-00-00 00:00:00' ...

  3. Newbit 启用淘宝店域名

    自2016-10-19起,我们正式启用淘宝店的域名,newbit.taobao.com 店里提供所有课程当中用到硬件,ZigBee插件/贴片模块等, 我们将坚持给大家提供最具扩展性,最方便使用的开发工 ...

  4. Kubernetes volumes简介

    容器中的磁盘文件生命周期比较短暂,在一些比较复杂的容器应用中会产生一些问题.一.容器crash后,kubelet会重启该容器,但这些文件会丢失掉.二.pod中的多个容器经常需要共享文件.因此,Kube ...

  5. PHP怎么获取系统信息和服务器详细信息

    https://zhidao.baidu.com/question/1435990326608475859.html 获取系统类型及版本号: php_uname() (例:Windows NT COM ...

  6. linux 下 用phpmailer类smtp发送邮件始终不成功,提示:ERROR: Failed to co

    https://zhidao.baidu.com/question/509191264.html?fr=iks&word=PHPMailerSMTP+connect()+failed& ...

  7. ip 百度地图 php

    已知一个IP $ipname=api_hits($DT_IP); -------------- //apifunction getAddressComponent($ak, $longitude, $ ...

  8. ffmpeg批量实现视频转码命令行

    ffmpeg实现视频转码命令行,result需要提前建好作为保存转码后的视频路径: ffmpeg -i .mp4 -vcodec h264 "result\1.mp4" 当有大量视 ...

  9. Efounds笔试

    Efounds的笔试~ 1.比较两个浮点数大小 一般不会直接用"=="或者"!="对两个浮点数进行比较. 判断两个浮点数float a 与 float b 是否 ...

  10. ora-01190和ora-01110的解决方法

    SQLPLUS>ALTER DATABASE DATAFILE 2 ONLINE; ALTER DATABASE DATAFILE 2 ONLINE * ERROR 位于第 1 行: ORA-0 ...