题目描述

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

输入输出格式

输入格式:

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

输出格式:

输出一个整数表示答案

输入输出样例

输入样例#1:
复制

aabb
bbaa
输出样例#1: 复制

10
将两串合并,中间加一个分隔符
先求出后缀数组和LCP的height数组
要求的就是后缀数组中不属于同一串的后缀的LCP
对于每一个(l,r)找到最小值位置minpos
在两边找来自两个不同串后缀数,分两种情况统计
然后分两边(l,minpos-1),(minpos,r)
用线段树维护
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long lol;
struct Seg
{
lol cnt[];
int x,pos;
}t[];
struct Data
{
int l,r;
};
int SA[],c[],rank[],x[],y[],len1,len2,n,m,s[];
char s1[],s2[];
queue<Data>Q;
lol ans,h[];
void build(int rt,int l,int r)
{
if (l==r)
{
if (SA[l]<len1) t[rt].cnt[]=;
if (SA[l]>len1) t[rt].cnt[]=;
t[rt].x=h[l];
t[rt].pos=l;
return;
}
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
t[rt].cnt[]=t[rt<<].cnt[]+t[rt<<|].cnt[];
t[rt].cnt[]=t[rt<<].cnt[]+t[rt<<|].cnt[];
if (t[rt<<].x<=t[rt<<|].x)
{
t[rt].pos=t[rt<<].pos;
t[rt].x=t[rt<<].x;
}
else
{
t[rt].pos=t[rt<<|].pos;
t[rt].x=t[rt<<|].x;
}
}
lol query_cnt(int rt,int l,int r,int L,int R,int x)
{
if (l>=L&&r<=R)
{
return t[rt].cnt[x];
}
int mid=(l+r)>>;
lol s=;
if (L<=mid) s+=query_cnt(rt<<,l,mid,L,R,x);
if (R>mid) s+=query_cnt(rt<<|,mid+,r,L,R,x);
return s;
}
int query_min(int rt,int l,int r,int L,int R)
{
if (l>=L&&r<=R)
{
return t[rt].pos;
}
int mid=(l+r)>>,s1=-,s2=-;
if (L<=mid) s1=query_min(rt<<,l,mid,L,R);
if (R>mid) s2=query_min(rt<<|,mid+,r,L,R);
if (s2==-) return s1;
if (s1==-) return s2;
if (h[s2]>=h[s1]) return s1;
return s2;
}
void radix_sort()
{int i;
for (i=;i<m;i++)
c[i]=;
for (i=;i<n;i++)
c[x[y[i]]]++;
for (i=;i<m;i++)
c[i]+=c[i-];
for (i=n-;i>=;i--)
SA[--c[x[y[i]]]]=y[i];
}
void build_SA()
{int i,j,k,p;
for (i=;i<n;i++)
x[i]=s[i],y[i]=i;
m=;
radix_sort();
for (k=;k<=n;k<<=)
{
p=;
for (i=n-k;i<n;i++)
y[p++]=i;
for (i=;i<n;i++)
if (SA[i]>=k) y[p++]=SA[i]-k;
radix_sort();
p=;
swap(x,y);
x[SA[]]=;
for (i=;i<n;i++)
x[SA[i]]=((y[SA[i]]==y[SA[i-]])&&((SA[i]+k<n?y[SA[i]+k]:-)==(SA[i-]+k<n?y[SA[i-]+k]:-)))?p-:p++;
if (p>=n) break;
m=p;
}
for (i=;i<n;i++)
rank[SA[i]]=i;
int L=;
for (i=;i<n;i++)
if (rank[i]>)
{
if (L>) L--;
j=SA[rank[i]-];
while (i+L<n&&j+L<n&&(s[i+L]==s[j+L])) L++;
h[rank[i]]=L;
}
}
int main()
{int i;
cin>>s1>>s2;
len1=strlen(s1),len2=strlen(s2);
for (i=;i<len1;i++)
s[i]=(int)s1[i];
s[len1]=(int)'#';
for (i=;i<len2;i++)
s[i+len1+]=(int)s2[i];
n=len1+len2+;
build_SA();
build(,,n-);
Q.push((Data){,n-});
while (Q.empty()==)
{
Data u=Q.front();
Q.pop();
int l=u.l,r=u.r;
int minpos=query_min(,,n-,l+,r);
//cout<<l<<' '<<r<<' '<<h[minpos]<<endl;
if (l<minpos-) Q.push((Data){l,minpos-});
if (minpos<r) Q.push((Data){minpos,r});
ans+=query_cnt(,,n-,l,minpos-,)*query_cnt(,,n-,minpos,r,)*h[minpos];
ans+=query_cnt(,,n-,l,minpos-,)*query_cnt(,,n-,minpos,r,)*h[minpos];
}
cout<<ans;
}

[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 ...

  10. BZOJ4566 [Haoi2016]找相同字符【SAM】

    BZOJ4566 [Haoi2016]找相同字符 给定两个字符串\(s和t\),要求找出两个字符串中所有可以相互匹配的子串对的数量 首先考虑可以怎么做,我们可以枚举\(t\)串的前缀\(t'\),然后 ...

随机推荐

  1. 基于 HTML5 Canvas 实现的文字动画特效

    前言 文字是网页中最基本的元素,一般我们在网页上都是展示的静态文字,但是就效果来说,还是比较枯燥的.文字淡入淡出的动画效果在项目中非常实用,如果有某些关键的文字,可以通过这种动态的效果来提醒用户阅读. ...

  2. Alpha第九天

    Alpha第九天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...

  3. Flask 扩展 Mail

    安装 pip install flask-mail from flask import Flask from flask_mail import Mail, Message app = Flask(_ ...

  4. Flask 部署和分发

    到目前为止,启动Flask应用都是通过"app.run()"方法,在开发环境中,这样固然可行,不过到了生产环境上,势必需要采用一个健壮的,功能强大的Web应用服务器来处理各种复杂情 ...

  5. 接触JS的变量

    刚刚接触到js,写的代码都是很简单的,制单的概念也相当少,新学习的就是变量.let和const以及js的数据类型. 变量的内容有五个,我就不一一介绍了,重点在于: 在 JavaScript 中,使用变 ...

  6. Python内置函数(16)——ord

    英文文档: ord(c) Given a string representing one Unicode character, return an integer representing the U ...

  7. JVM学习记录

    本博客是为了自己学习JVM而建立,只记录一些自己学习的经过. 最近在看<深入理解Java虚拟机>这本书,里面的内容,很是乏味,因为看不懂所以就会觉得很枯燥,觉得很枯燥看着看着就犯困,然后就 ...

  8. java 实现多文件打包下载

    jsp页面js代码: function downloadAttached(){ var id = []; id.push(infoid); var options = {}; options.acti ...

  9. api-gateway实践(06)新服务网关 - 请求监控

    一.实时监控 用户点击服务实例,系统显示服务实例-version下的api列表, 用户点击某个api的如下两个图标 1.API请求次数监控 横轴:时间,粒度为分钟 纵轴:请求访问次数 展示:失败数(红 ...

  10. 新概念英语(1-59)Is that all

    Does the lady buy any chalk? A:I want some envelopes, please. B:Do you want the large size or the sm ...