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

Description

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

Input

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

Output

输出一个整数表示答案

Sample Input

aabb
bbaa

Sample Output

10

对两个串建立广义后缀自动机。
设siz[i][0],siz[i][1]分别表示这个串分别在两个串中出现多少次,这个后缀树上DP即可求出。
答案就是(dep[p]-dep[fa[p]])*siz[p][0]*siz[p][1]。
注意插入每个串之前要重置lst=1
 
代码:
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 800050
typedef long long ll;
int ch[N<<1][26],fa[N<<1],dep[N<<1],siz[N<<1][2],cnt=1,lst=1;
int ws[N],a[N];
char w[N],s[N];
void insert(int x) {
int p=lst,np,q,nq;
if(ch[p][x]) {
q=ch[p][x];
if(dep[q]==dep[p]+1) lst=q;
else {
fa[nq=++cnt]=fa[q]; lst=nq;
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}else {
np=++cnt; lst=np; dep[np]=dep[p]+1;
for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
if(!p) fa[np]=1;
else {
q=ch[p][x];
if(dep[q]==dep[p]+1) fa[np]=q;
else {
fa[nq=++cnt]=fa[q];
dep[nq]=dep[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[q]=fa[np]=nq;
for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
}
}
}
}
void print() {
int i,j;
printf("test-------------------------------------------\n");
for(i=1;i<=cnt;i++) {
printf("p=%d,siz=%d,dep=%d,fa=%d\n",i,siz[i][0],dep[i],fa[i]);
for(j=0;j<26;j++) {
if(ch[i][j]) {
printf("ch(%d)(%c)=%d\n",i,j+'a',ch[i][j]);
}
}
}
printf("lst=%d\n",lst);
}
int main() {
scanf("%s%s",w+1,s+1);
int lw=strlen(w+1),ls=strlen(s+1);
int i;
for(i=1;i<=lw;i++) insert(w[i]-'a'),siz[lst][0]++;
lst=1;
for(i=1;i<=ls;i++) insert(s[i]-'a'),siz[lst][1]++;
// print();
for(i=1;i<=cnt;i++) ws[dep[i]]++;
for(i=1;i<=cnt;i++) ws[i]+=ws[i-1];
for(i=1;i<=cnt;i++) a[ws[dep[i]]--]=i;
for(i=cnt;i;i--) {
int p=a[i];
siz[fa[p]][0]+=siz[p][0];
siz[fa[p]][1]+=siz[p][1];
}
ll ans=0;
for(i=cnt;i;i--) {
int p=a[i];
ans+=1ll*(dep[p]-dep[fa[p]])*siz[p][0]*siz[p][1];
}
printf("%lld\n",ans);
}

BZOJ_4566_[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】找相同字符(后缀自动机)

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

  6. BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机)

    BZOJ4566&&lg3181 HAOI找相同字符(广义后缀自动机) 题面 自己找去 HINT 给定两个文本串,问从两个串中各取一个非空子串,使这俩子串相同,问方案有多少种.我的思路 ...

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

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

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

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

  9. BZOJ4566 [Haoi2016]找相同字符 【后缀数组】

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

随机推荐

  1. Laya 利用JS进行反射

    Laya 利用JS进行反射 @author ixenos 当需要配表调用函数时,可以利用js的eval来调用 1.在配置js中写下: function callAsFunc(funcName){ ev ...

  2. kafka直连方式消费多个topic

    一个消费者组可以消费多个topic,以前写过一篇一个消费者消费一个topic的,这次的是一个消费者组通过直连方式消费多个topic,做了小测试,结果是正确的,通过查看zookeeper的客户端,zoo ...

  3. 【HDOJ6335】Nothing is Impossible(贪心)

    题意: 有n道题目m个人,每道题目有1个正确选项和a[i]个错误选项,每个人每道题只能选一个选项 求出最坏情况下分数最多的人至少能拿到几分 n<=1e2,m<=1e9,1<=b[i] ...

  4. wordpress优化:Gravatar头像被墙及解决方案

    网站缓存现象: 打开网站是左下角出现0.gravatar.com.1.gravatar.com或2.gravatar.com字样,网站一直处于缓存状态,迟迟未能打开.很多人都会缺乏耐心地等待一个网页的 ...

  5. django学习之- CSRF及中间件

    CSRF # 表示django全局发送post请求均需要字符串验证功能:防止跨站请求伪造的功能工作原理:客户端访问服务器端,在服务器端正常返回给客户端数据的时候,而外返回给客户端一段字符串,等到客户端 ...

  6. Java操作XML牛逼利器JDOM&DOM4J

    JDOM  JDOM 是一种使用 XML(标准通用标记语言下的一个子集) 的独特 Java 工具包,用于快速开发 XML 应用 程序. JDOM 官方网站:http://www.jdom.org/ 利 ...

  7. java内存区域和对象的产生

    一直被java中内存组成弄的头晕眼花,这里总结下都有哪些,先上图片 程序计数器 小块内存,线程执行字节码的信号指示器,以此获取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复都要依赖他 ...

  8. win7电脑定时开机设置方法

    在BIOS设置主界面中选择“Power Management Setup”,进入“电源管理”窗口. 注:缺省情况下,“Resume By Alarm”定时开机选项是关闭的. 将鼠标移到“Resume ...

  9. Linux中断处理驱动程序编写

    本章节我们一起来探讨一下Linux中的中断 中断与定时器:中断的概念:指CPU在执行过程中,出现某些突发事件急待处理,CPU暂停执行当前程序,转去处理突发事件,处理完后CPU又返回原程序被中断的位置继 ...

  10. 使用Android SwipeRefreshLayout了解Android的嵌套滑动机制

    SwipeRefreshLayout 是在Android Support Library, revision 19.1.0加入到support v4库中的一个下拉刷新控件,关于android的下拉刷新 ...