题意

给定两个字符串,求两个字符串相同子串的方案数。

分析

那么将字符串s1建SAM,然后对于s2的每个前缀,都在SAM中找出来,并且计数就行。

我一开始的做法是,建一个u和len,顺着s2跑SAM,当st[u].next[c]存在的时候,u=st[u].next[c],len++,这时候找到了这个前缀的最长公共后缀,然后顺着parent边向上走,然后res+=cnt[u]*(len-st[st[u].link].len)。为什么是len-st[st[u].link].len。因为对于状态u,它的有效长度是[st[st[u].link].len+1,st[u].len]。但是这样写完以后TLE了。然后我就去看了下大佬们的做法。思路也是一样的只是记录一个f数组。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream> using namespace std;
const int maxn=+;
typedef long long LL;
struct state{
int len,link;
int next[];
}st[*maxn];
int cnt[*maxn],c[*maxn],ap[*maxn];
LL f[*maxn];
char s1[maxn],s2[maxn];
int n1,n2;
int last,cur,sz;
void init(){
sz=;
last=cur=;
st[].link=-;
st[].len=;
} void build_sam(int c){
cur=sz++;
cnt[cur]=;
st[cur].len=st[last].len+;
int p;
for(p=last;p!=-&&st[p].next[c]==;p=st[p].link)
st[p].next[c]=cur;
if(p==-)
st[cur].link=;
else{
int q=st[p].next[c];
if(st[q].len==st[p].len+)
st[cur].link=q;
else{
int clone=sz++;
st[clone].len=st[p].len+;
st[clone].link=st[q].link;
for(int i=;i<;i++)
st[clone].next[i]=st[q].next[i];
for(;p!=-&&st[p].next[c]==q;p=st[p].link)
st[p].next[c]=clone;
st[cur].link=st[q].link=clone;
}
}
last=cur;
}
int cmp(int a,int b){
return st[a].len>st[b].len;
} LL update(int u,int len){
LL res=;
while(u){
res+=(LL)(len-st[st[u].link].len)*cnt[u];
u=st[u].link,len=st[u].len;
}
return res;
} int main(){
scanf("%s%s",s1,s2);
n1=strlen(s1),n2=strlen(s2);
init();
for(int i=;i<n1;i++){
build_sam(s1[i]-'a');
}
for(int i=;i<sz;i++)
c[i]=i;
sort(c,c+sz,cmp);
for(int i=;i<sz;i++){
int o=c[i];
if(st[o].link!=-)
cnt[st[o].link]+=cnt[o];
} LL ans=;
int u=,len=;
for(int i=;i<n2;i++){
int c=s2[i]-'a';
while(u!=-&&st[u].next[c]==)
u=st[u].link,len=st[u].len;
if(u==-)
u=,len=;
else{
u=st[u].next[c],len++;
// ans+=update(u,len);
ap[u]++,ans+=(LL)cnt[u]*(len-st[st[u].link].len);
}
} for(int i=;i<sz;i++){
int o=c[i];
if(st[o].link!=-)
f[st[o].link]+=f[o]+ap[o];
}
for(int i=;i<sz;i++){
ans+=(LL)cnt[i]*f[i]*(st[i].len-st[st[i].link].len);
}
printf("%lld\n",ans);
return ;
}

【BZOJ4566】找相同字符【后缀自动机】的更多相关文章

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

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

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

    4566: [Haoi2016]找相同字符 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 275  Solved: 155[Submit][Statu ...

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

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

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

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

  5. 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈

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

  6. [HAOI2016] 找相同字符 - 后缀数组,单调栈

    [HAOI2016] 找相同字符 Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. \(n,m \l ...

  7. bzoj4566 找相同字符

    题意:给定两个字符串,从中各取一个子串使之相同,有多少种取法.允许本质相同. 解:建立广义后缀自动机,对于每个串,分别统计cnt,之后每个点的cnt乘起来.记得开long long #include ...

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

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

  9. bzoj4566 / P3181 [HAOI2016]找相同字符

    P3181 [HAOI2016]找相同字符 后缀自动机 (正解应是广义后缀自动机) 并不会广义后缀自动机. 然鹅可以用普通的后缀自动机.   我们先引入一个问题:算出从一个串内取任意两个不重合子串完全 ...

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

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

随机推荐

  1. MEF学习总结(4)---Container层

    通过AttributeedModelPrograming,我们可以声明暴露组件,依赖组件,发现组件,但是所有这些需要有一个触发点.即需要把所有这些组合在一起来协同工作,最终实现依赖注入.这就是Cont ...

  2. 题目1413:神秘元素 ——lis的元素是否唯一

    求序列的最长子序列中不可分割元素的数目.不可分割元素,肯定属于某一个最长子序列,首先做的就是把属于最长子序列的数提取出来,减小查找范围.怎么提取?可以用LIS(最长递增子序列)和LDS(最长递减子序列 ...

  3. mysql大数据量之limit优化

    背景:当数据库里面的数据达到几百万条上千万条的时候,如果要分页的时候(不过一般分页不会有这么多),如果业务要求这么做那我们需要如何解决呢?我用的本地一个自己生产的一张表有五百多万的表,来进行测试,表名 ...

  4. Java格式化时间为String类型

    SimpleDateFormat ormater = new SimpleDateFormat("yyyy-MM-dd"); Date date=new Date(); Strin ...

  5. Unit06: 状态管理-cookie

    Unit06: 状态管理-cookie web package web; import java.io.IOException; import java.io.PrintWriter; import ...

  6. Java堆栈解析

    1.RAM和ROM区别RAM-RamdomAccessMemory随机存取存储器(断电后数据会丢失),高速存取,读写时间相等,且与地址无关,如计算机内存等. ROM-Read Only Memory只 ...

  7. 30个让人兴奋的视差滚动(Parallax Scrolling)效果网站--转

    视差滚动(Parallax Scrolling)是指让多层背景以不同的速度移动,形成立体的运动效果,带来非常出色的视觉体验.作为今年网页设计的热点趋势,越来越多的网站应用了这项技术.今天这篇文章就与大 ...

  8. 第三章 Istio基本介绍

    3.1 Istio的核心组件及其功能 Istio总体分两部分:控制面和数据面. 数据面(sidecar):sidecar通过注入的方式和业务容器共存于一个pod,会劫持业务容器的流量,并接受控制面组件 ...

  9. mongoDB的权限管理

    最近做一个关于mongoDB权限的功能, 在网上找了好久,各种命令,各种配置,各种修改,都没有解决哥的困惑.无奈,睡一觉后,灵光乍现,灵感来了. 下面就是我的最新发现,当然在各位看官的眼里,我的这个也 ...

  10. css:层叠样式表-网页布局基础

    css:层叠样式表:一.写法分类: 1.内联(行内,写在标签里面,以属性的形式表现,属性名是style) 例:<table style="background-color: aqua& ...