题目描述

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

输入输出格式

输入格式:

两行,两个字符串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. hibernate框架学习笔记11:Criteria查询详解

    创建实体类对象: package domain; import java.util.HashSet; import java.util.Set; //客户实体 public class Custome ...

  2. ruby:TypeError: 对象不支持此属性或方法

    解决办法. 1.下载对应版本 下载node.js,根据ruby版本决定下载32还是x64,我的ruby版本x64 https://npm.taobao.org/mirrors/node/v8.9.3/ ...

  3. 完美解决某法院HP EVA8400删除VDISK问题

    [故障描述] 某地法院一台HP EVA8400存储,2组扩展柜,物理磁盘由12个1T FATA磁盘(AG691A 454414-001)和10个300G 15K FC磁盘(AG690A 454411- ...

  4. 02-移动端开发教程-CSS3新特性(中)

    1. 新的背景 背景在CSS3中也得到很大程度的增强,比如背景图片尺寸.背景裁切区域.背景定位参照点.多重背景等. 1.1 background-size设置背景图片的尺寸 cover会自动调整缩放比 ...

  5. C# 封装miniblink 使用HTML/CSS/JS来构建.Net 应用程序界面和简易浏览器

    MiniBlink的作者是 龙泉寺扫地僧 miniblink是什么?   (抄了一下 龙泉寺扫地僧 写的简洁) Miniblink是一个全新的.追求极致小巧的浏览器内核项目,其基于chromium最新 ...

  6. System V IPC 之消息队列

    消息队列和共享内存.信号量一样,同属 System V IPC 通信机制.消息队列是一系列连续排列的消息,保存在内核中,通过消息队列的引用标识符来访问.使用消息队列的好处是对每个消息指定了特定消息类型 ...

  7. Java基础类库简介

    Java基础类库简介 一.常用的基础类库:11个jar(Java Archive,Java归档)包 作为java语言使用者,我们可以感受到java语言带来的优势(平台无关.面向对象.多线程.高效易扩展 ...

  8. OpenShift实战(二):OpenShift节点扩容

    1.新增节点信息 增加节点如下,请将xxx改为自己的域名 node6.xxx.net Node 192.168.8.90 8G 20G/60G 4C node7.xxx.net Node 192.16 ...

  9. C#中DBNull.Value和Null的用法和区别

    DBNull.Value,, 是适用于向数据库的表中插入空值.而 null,是指在程序中表示空引用. 或者对象为空.就是没有实例化. row[column]的值为DBNull.Value的话,至少说明 ...

  10. 新概念英语(1-107)It's Too Small.

    Lesson 107 It's too small. 太小了. Listen to the tape then answer this question. What kind of dress doe ...