[BZOJ4566][HAOI2016]找相同子串
用SAM重新写了一遍..
我的方法比较笨,先把两个串连在一起,算出来相同子串个数,同理算出s1和s2的子串个数。作差即可。
至于如何统计子串个数,首先toposort后搞出right集的大小,然后$C_{|right|}^{2} \times (step[i]-step[fa])$就是答案。
//BZOJ 4565
//by Cydiater
//2017.1.21
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <ctime>
#include <iomanip>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define FILE "find_2016"
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
char s1[MAXN],s2[MAXN],s[MAXN];
int len1,len2;
struct SAM{
int now,cnt,son[MAXN][30],step[MAXN],pre[MAXN],rnk[MAXN],label[MAXN];
ll g[MAXN],ans;
SAM(){now=1;cnt=1;}
void Extend(int nxt){
int p=now,np=++cnt;now=np;g[np]=1;
step[np]=step[p]+1;
for(;p&&!son[p][nxt];p=pre[p])son[p][nxt]=np;
if(!p)pre[np]=1;
else{
int q=son[p][nxt],nq;
if(step[q]==step[p]+1)pre[np]=q;
else{
step[(nq=++cnt)]=step[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
pre[nq]=pre[q];
pre[np]=pre[q]=nq;
for(;son[p][nxt]==q;p=pre[p])son[p][nxt]=nq;
}
}
}
void Build(int len){
up(i,1,len)Extend(s[i]-'a');
}
void Clear(){
now=cnt=1;
memset(pre,0,sizeof(pre));
memset(son,0,sizeof(son));
memset(step,0,sizeof(step));
memset(g,0,sizeof(g));
memset(label,0,sizeof(label));
memset(rnk,0,sizeof(rnk));
}
ll col(int len){
//topsort
ans=0;
up(i,1,cnt)label[step[i]]++;
up(i,1,len)label[i]+=label[i-1];
up(i,1,cnt)rnk[label[step[i]]--]=i;
down(i,cnt,2){
int node=rnk[i];
if(g[node]>=2)
ans+=(g[node]*(g[node]-1)>>1)*(ll)(step[node]-step[pre[node]]);
g[pre[node]]+=g[node];
}
return ans;
}
}sam;
namespace solution{
void Prepare(){
scanf("%s",s1+1);
len1=strlen(s1+1);
scanf("%s",s2+1);
len2=strlen(s2+1);
}
void Solve(){
ll ans1,ans2,ans3;
memcpy(s,s1,sizeof(s));
sam.Build(len1);
ans1=sam.col(len1);
sam.Clear();
memcpy(s,s2,sizeof(s));
sam.Build(len2);
ans2=sam.col(len2);
sam.Clear();
memcpy(s,s1,sizeof(s));
s[len1+1]='a'+26;
up(i,len1+2,len1+len2+1)s[i]=s2[i-len1-1];
sam.Build(len1+len2+1);
ans3=sam.col(len1+len2+1);
//cout<<ans1<<' '<<ans2<<' '<<ans3<<endl;
ans3-=ans1+ans2;
cout<<ans3<<endl;
}
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
using namespace solution;
Prepare();
Solve();
return 0;
}
看了看别人用SAM实现的代码,发现其实不必要那样。对于s1建一个sam,统计每个点的路径对应多少个子串。然后s2串在SAM上跑,经过一个点就统计上父亲点的sum(因为变换了位置)再加上当前对应的字符串的数量就行了。
[BZOJ4566][HAOI2016]找相同子串的更多相关文章
- BZOJ4566 [Haoi2016]找相同字符【SAM】
BZOJ4566 [Haoi2016]找相同字符 给定两个字符串\(s和t\),要求找出两个字符串中所有可以相互匹配的子串对的数量 首先考虑可以怎么做,我们可以枚举\(t\)串的前缀\(t'\),然后 ...
- 字符串(后缀数组):HAOI2016 找相同子串
[HAOI2016]找相同子串 [题目描述] 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两个子串中有一个位置不同. [输入格式] 两行,两个字符 ...
- [BZOJ4566][Haoi2016]找相同字符 后缀自动机+dp
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1212 Solved: 694[Submit][Stat ...
- [Bzoj4566][Haoi2016]找相同字符(广义后缀自动机)
4566: [Haoi2016]找相同字符 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 861 Solved: 495[Submit][Statu ...
- BZOJ4566: [Haoi2016]找相同字符
Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...
- BZOJ4566 [Haoi2016]找相同字符 字符串 SAM
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ4566.html 题目传送门 - BZOJ4566 题意 给定两个字符串 $s1$ 和 $s2$ ,问有 ...
- BZOJ4566 Haoi2016 找相同字符【广义后缀自动机】
Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...
- BZOJ4566:[HAOI2016]找相同字符(SAM)
Description 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. Input 两行,两个字符串s1,s2,长度分别 ...
- BZOJ4566 [Haoi2016]找相同字符 【后缀数组】
题目 给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数.两个方案不同当且仅当这两 个子串中有一个位置不同. 输入格式 两行,两个字符串s1,s2,长度分别为n1,n2.1 & ...
随机推荐
- XStream中几个注解的含义和用法
转自:http://blog.csdn.net/robert_mm/article/details/8459879 XStream是个很强大的工具,能将java对象和xml之间相互转化.xstream ...
- Python中的一些函数
1. 中文繁体/简体转换 下载 zh_wiki.py:https://github.com/skydark/nstools/blob/master/zhtools/zh_wiki.py 和 langc ...
- SpringBoot--属性加载顺序
属性加载顺序: 1.在命令行中传入的参数: 2.SPRING_APPLICATION_JSON中的属性:SPRING_APPLICATION_JSON是以JSON格式配置在系统环境变量中内容: 3.j ...
- 安装mysql最后一步未响应,卡死。(解决方法mySql5.5,以及安装教程)
安装教程:http://www.server110.com/mysql/201308/784.html 重装mysql的时候,总是在提交配置后的最后一步,安装失败,进程管理器里显示程序无响应,mysq ...
- Sublime Text 配置成 C++ IDE
在Windows中将Sublime Text配置成C++的IDE.首先,为了运行C++需要安装g++编译器,g++可直接在codeblocks中找到.codeblock的官网下载地址是http://w ...
- 如何在 windows 配置 libtorch c++ 前端库?
如何在 windows 配置 libtorch c++ 前端库? 下载 pytorch 已经编译好的库: 此库不带 gpu,主要方便演示.支持 win7 win10 系统. 下载地址:https:// ...
- Python高级特性(3): Classes和Metaclasses(转)
原文:Python高级特性(3): Classes和Metaclasses 类和对象 类和函数一样都是Python中的对象.当一个类定义完成之后,Python将创建一个“类对象”并将其赋值给一个同名变 ...
- OVN实战---《OVN and Containers》翻译
Overview 在本篇文章中,我们要讨论的是OVN和容器的集成.到本次实验中,我们将会创建一个包含有一对容器的“虚拟机”,这些容器会直接和OVN logical switch相连,并且可以供逻辑网络 ...
- C#版-Redis缓存服务器在Windows下的使用
Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token.短信验证码等 官网显示Redis本身并没有Wind ...
- 【开发者笔记】归并排序过程呈现之java内置GUI表示
在网上看到一个视频将各种排序用视频表示出来,配上音乐,挺好玩的样子,就算是不会编程的人看到也会觉得很舒服,碰巧我也正在写归并算法,于是就用java的GUI实现一个. 归并排序的时间复杂度是T(n)=O ...