poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415
因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献。
一开始想的是把两个数组接起来(中间加个逗号之类的,就能算出正确的 LCP ),不加区分地算了贡献之后再分别减去两个数组自己内部的贡献。
看看题解,得知可以在那个接起来的数组上分别算 a 与前面的 b 、b 与前面的 a 的贡献,就不用容斥了。
考虑怎么算贡献。一开始想的是取 min 一定越取越小,所以维护双指针卡在取min>=K的最靠前位置;新加入一个元素的时候二分找到第一个取min后比自己小的位置,改一下该位置到自己位置的贡献(现在看来好像不用维护那个双指针也行?);
看看题解,原来可以用单调栈。就相当于维护一下单调栈的“面积”一样。
不过有一点麻烦的是 i 位置能否产生贡献是看 i+1 位置到末尾位置的 min ;这样求“面积”就要费点心;不过想到可以让 ht[ i ] = ht[ i+1 ] ,这样的话正常求面积就行了!累计到答案上之后再把当前位置入队。
注意有大写字母。而且 poj 上编译不过 swap( rk , tp ) ,写 memcpy 就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+,M=N<<;
int n,m,s[M],sa[M],rk[M],tp[M],tx[M],ht[M];
int sta[M],top,wd1[M],wd2[M]; ll sm1[M],sm2[M];
char a[N],b[N];
int Mx(int a,int b){return a>b?a:b;}
void Rsort(int n,int nm)
{
for(int i=;i<=nm;i++)tx[i]=;
for(int i=;i<=n;i++)tx[rk[i]]++;
for(int i=;i<=nm;i++)tx[i]+=tx[i-];
for(int i=n;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
}
void get_sa(int n)
{
int nm=;
for(int i=;i<=n;i++)tp[i]=i,rk[i]=s[i];
Rsort(n,nm);
for(int k=;k<=n;k<<=)
{
int tot=;
for(int i=n-k+;i<=n;i++)tp[++tot]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++tot]=sa[i]-k;
Rsort(n,nm);
memcpy(tp,rk,sizeof rk);
/*swap(rk,tp);*/nm=;rk[sa[]]=;
for(int i=,u,v;i<=n;i++)
{
u=sa[i]+k;v=sa[i-]+k;if(u>n)u=;if(v>n)v=;
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?nm:++nm;
}
if(nm==n)break;
}
}
void get_ht(int n)
{
int k=,j;
for(int i=;i<=n;i++)
{
for(j=sa[rk[i]-],k?k--:;i+k<=n&&j+k<=n&&s[i+k]==s[j+k];k++);
ht[rk[i]]=k;
}
}
int main()
{
while()
{
int lm;scanf("%d",&lm);if(!lm)return ;
scanf("%s",a+);scanf("%s",b+);
n=strlen(a+); m=strlen(b+); int tn=n+m+;
for(int i=;i<=n;i++)s[i]=a[i]-'A'+;
s[n+]=;
for(int i=n+,j=;i<=tn;i++,j++)s[i]=b[j]-'A'+;
get_sa(tn);get_ht(tn); for(int i=;i<tn;i++)ht[i]=ht[i+];
top=; ll ans=;
for(int i=;i<=tn;i++)
{
if(sa[i]<=n)ans+=sm2[top]; else if(sa[i]>n+)ans+=sm1[top];
int lj1=,lj2=;
while(top&&ht[i]<=ht[sta[top]])
lj1+=wd1[top],lj2+=wd2[top],top--;
sta[++top]=i;
if(sa[i]<=n)lj1++; else if(sa[i]>n+)lj2++;
wd1[top]=lj1; sm1[top]=sm1[top-]+(ll)lj1*Mx(,ht[i]-lm+);
wd2[top]=lj2; sm2[top]=sm2[top-]+(ll)lj2*Mx(,ht[i]-lm+);
}
printf("%lld\n",ans);
}
return ;
}
poj 3415 Common Substrings——后缀数组+单调栈的更多相关文章
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈
题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...
- POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)
Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- POJ 3415 Common Substrings 后缀数组+并查集
后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法, 首先将两个串 连接起来求height 求完之后按height值从大往小合并. height值代表的是 sa[i]和sa[i ...
- POJ - 3415 Common Substrings (后缀数组)
A substring of a string T is defined as: T( i, k)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|. Given two s ...
- poj 3415 Common Substrings【SA+单调栈】
把两个串中间加一个未出现字符接起来,然后求SA 然后把贡献统计分为两部分,在排序后的后缀里,属于串2的后缀和排在他前面属于串1的后缀的贡献和属于串1的后缀和排在他前面属于串2的后缀的贡献 两部分分别作 ...
- POJ 3415 Common Substrings ——后缀数组
[题目分析] 判断有多少个长度不小于k的相同子串的数目. N^2显然是可以做到的. 其实可以维护一个关于height的单调栈,统计一下贡献,就可以了. 其实还是挺难写的OTZ. [代码] #inclu ...
随机推荐
- JSONObject使用方法
转载:http://blog.csdn.net/dongzhouzhou/article/details/8664569 1.JSONObject介绍 JSONObject-lib包是一个beans, ...
- GIT生成 SSH Key步骤
//设置user.name和email 提交到git之后会显示用户名(在随意一个目录打开git-bash执行就行)Administrator@DESKTOP-BP3H0HS MINGW64 /d/mi ...
- 分享会上演示Dubbo的路由规则,结果被小坑了下
今天公司给大家演示基于Dubbox的服务治理平台,结果因为开了vpn导致本机IP地址比较混乱,在配置路由规则的时候我这样配置条件路由 consumer.host=*.*.*.* => pro ...
- Spring Cloud 与 Spring boot - 转载
微服务是这样一个结构吗? 前端或二方 - > ng集群 -> zuul集群 -> eureka-server集群 -> service provider集群 (二方指其他业务部 ...
- Java中的条件运算符
条件运算符( ? : )也称为 “三元运算符”. 语法形式:布尔表达式 ? 表达式1 :表达式2 运算过程:如果布尔表达式的值为 true ,则返回 表达式1 的值,否则返回 表达式2 的值 例如: ...
- BZOJ 1492 [NOI2007]货币兑换Cash:斜率优化dp + cdq分治
传送门 题意 初始时你有 $ s $ 元,接下来有 $ n $ 天. 在第 $ i $ 天,A券的价值为 $ A[i] $ ,B券的价值为 $ B[i] $ . 在第 $ i $ 天,你可以进行两种操 ...
- ImageView显示图像控件
ImageView显示图像控件 一.简介 1. 2. ImageView,图像视图,直接继承自View类,它的主要功能是用于显示图片,实际上它不仅仅可以用来显示图片,任何Drawable对象都可以使用 ...
- kindeditor上传本地图片实例
所需插件:kindeditor下载 密码: 5ry4 jsp文件: <script type="text/javascript" language="javas ...
- CC 攻击检测研究现状
网络层ddos 是让去往银行的道路交通变得拥堵,无法使正真要去银行的人到达:常利用协议为网络层的,如tcp(利用三次握手的响应等待及电脑tcp 连接数限制)等应用层ddos 则是在到达银行后通过增办. ...
- 【scala】可变参数
Scala允许使用可变的参数列表. 语法 在声明的参数类型后边添加星号(*) 示例 object HelloWorld{ def hello(args:String*): Unit ={ for(ar ...