题意

考虑将\(s1\)和\(s2\)接在一起求出相同子串个数,再求出\(s1\)自己匹配的相同子串个数和\(s2\)自己匹配的相同子串个数减去即可。

如何求相同子串个数:

我们知道子串的集合即所有后缀的前缀集合,于是实际上答案就是:

\(\sum\limits_{i=1}^n\sum\limits_{j=i+1}^nlcp(sa_i,sa_j)\)

接下来就和这题相同了。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=400010;
int n,m,num,top;
int sa[maxn],rk[maxn],oldrk[maxn],id[maxn],tmpid[maxn],cnt[maxn],height[maxn],L[maxn],R[maxn],sta[maxn];
ll ans;
char s1[maxn],s2[maxn],s[maxn];
inline bool check(int x,int y,int k){return oldrk[x]==oldrk[y]&&oldrk[x+k]==oldrk[y+k];}
inline void get_sa(char* s,int len)
{
memset(cnt,0,sizeof(cnt));
num=300;
for(int i=1;i<=len;i++)cnt[rk[i]=s[i]]++;
for(int i=1;i<=num;i++)cnt[i]+=cnt[i-1];
for(int i=len;i;i--)sa[cnt[rk[i]]--]=i;
for(int t=1;t<=len;t<<=1)
{
int tot=0;
for(int i=len-t+1;i<=len;i++)id[++tot]=i;
for(int i=1;i<=len;i++)if(sa[i]>t)id[++tot]=sa[i]-t;
tot=0;
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=len;i++)cnt[tmpid[i]=rk[id[i]]]++;
for(int i=1;i<=num;i++)cnt[i]+=cnt[i-1];
for(int i=len;i;i--)sa[cnt[tmpid[i]]--]=id[i];
memcpy(oldrk,rk,sizeof(rk));
for(int i=1;i<=len;i++)rk[sa[i]]=check(sa[i-1],sa[i],t)?tot:++tot;
num=tot;
if(num==len)break;
}
for(int i=1,j=0;i<=len;i++)
{
if(j)j--;
while(s[i+j]==s[sa[rk[i]-1]+j])j++;
height[rk[i]]=j;
}
}
inline ll calc(int len)
{
ll res=0;
sta[top=1]=1;
for(int i=2;i<=len;i++)
{
while(top&&height[sta[top]]>=height[i])R[sta[top--]]=i;
L[i]=sta[top];sta[++top]=i;
}
while(top)R[sta[top--]]=len+1;
for(int i=2;i<=len;i++)res+=1ll*height[i]*(R[i]-i)*(i-L[i]);
return res;
}
int main()
{
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1),m=strlen(s2+1);
get_sa(s1,n);ans-=calc(n);
get_sa(s2,m);ans-=calc(m);
for(int i=1;i<=n;i++)s[i]=s1[i];
s[n+1]='#';
for(int i=1;i<=m;i++)s[n+i+1]=s2[i];
get_sa(s,n+m+1);ans+=calc(n+m+1);
printf("%lld\n",ans);
return 0;
}

luoguP3181 [HAOI2016]找相同字符的更多相关文章

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

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

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

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

  3. 【BZOJ4566】[HAOI2016]找相同字符

    [BZOJ4566][HAOI2016]找相同字符 题面 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. 其中\(1\le ...

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

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

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

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

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

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

  7. [Bzoj4566][Haoi2016]找相同字符(广义后缀自动机)

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

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

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

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

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

随机推荐

  1. RabbitMQ学习笔记(四、RabbitMQ队列)

    目录: 消息路由失败了会怎样 备份交换器 TTL与DLX 如何实现延迟队列 RabbitMQ的RPC实现 持久化 事务 发送方确认机制 消息路由失败了会怎样: 在RabbitMQ中,如果消息路由失败了 ...

  2. MYSQL的备份与恢复--物理备份xrabackup

    目录 1.数据库完整备份与恢复 (1)环境准备 (2)完全备份恢复流程 2.数据库增量备份与恢复 (1)增量和差异概述 (2)增量备份和恢复 3.数据库差异备份与恢复 4.简单命令进行物理备份 5.实 ...

  3. 201871010118-唐敬博《面向对象程序设计(java)》第一周学习总结

    博文正文开头格式:(3分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/p/11435127.html 这个作业的要求在哪里 https:/ ...

  4. bzoj3293 分金币

    题目链接 problem 圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除.每个人可以给他左右相邻的人一些金币,最终使 得每个人的金币数目相等.你的任务是求出被转手的金币数量的最小值. so ...

  5. Sql Server 判断表是否存在方法总结

    #使用场景: 1.在创建表之前,需要先判断该表是否已经存在: 2.在删除表之前,需要先判断该表是否已经存在: #方法总结: 1.判断实体表是否存在的方法: 1).方法一: * from sysObje ...

  6. 【Oracle命令】sql语句之排序(order by)

    通过对数据库数据进行降序排序来达到显示最新数据在前面的效果 -- 降序排序(最新的显示在前面) SELECT * FROM 表名 t ORDER BY t.uploadDatetime DESC; 格 ...

  7. VRF--虚拟路由表

    VRF Virtual routing forwarding,虚拟路由转发表,简称VPN.他能在两个site之间建立两个不用的路由表,相互隔离,把每台交换机逻辑上分成多台虚拟交换机,即多VPN路由转发 ...

  8. MySQL,必须掌握的6个知识点

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  9. Go文件内容追加问题

    今天在用文件追加时,遇到点小问题,一直没法追加,起初是这样的 fp,err1 = os.OpenFile(filename,os.O_APPEND,0666) 上面这个死活加不了,后面改成 fp,er ...

  10. 前端开发工具HBuilder使用技巧以及快捷键

    创建HTML结构: h 8 (敲h激活代码块列表,按8选择第8个项目,即HTML代码块,或者敲h t Enter) 中途换行: 'Ctrl+Enter' 设置charset: m e 6 Enter ...