【POJ3415】Common Substrings(后缀数组,单调栈)
题意:

n<=1e5
思路:

我的做法和题解有些不同
题解是维护A的单调栈算B的贡献,反过来再做一次
我是去掉起始位置不同这个限制条件先算总方案数,再把两个串内部不合法的方案数减去
式子展开之后是 sigma(lcp(i,j))-K*L*(L+1)/2+合法(i,j)对数,其中L为连续的height[i]>=K的区域长度
sigma(lcp(i,j))计算部分与BZOJ3238类似
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second
#define MP make_pair
#define N 210000
#define MOD 1000000007
#define eps 1e-8
#define pi acos(-1)
#define oo 1000000000 char a[N],b[N];
int n,i,s[N],sa[N],wa[N],wb[N],wc[N],wd[N],height[N],rank[N],
H[N],stk[N];
ll ans,K,c[N],d[N]; int read()
{
int v=,f=;
char c=getchar();
while(c<||<c) {if(c=='-') f=-; c=getchar();}
while(<=c&&c<=) v=(v<<)+v+v+c-,c=getchar();
return v*f;
} bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
} void getsa(int *r,int *sa,int n,int m)
{
int *x=wa,*y=wb,j,p;
for(i=;i<n;i++) wc[x[i]=r[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p)
{
p=;
for(i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++)
if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=;i<n;i++) wd[i]=x[y[i]];
for(i=;i<m;i++) wc[i]=;
for(i=;i<n;i++) wc[wd[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[wd[i]]]=y[i];
swap(x,y);
p=; x[sa[]]=;
for(i=;i<n;i++) x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
} void getheight(int *r,int *sa,int n)
{
int i,j,k=;
for(i=;i<=n;i++) rank[sa[i]]=i;
for(i=;i<n;height[rank[i++]]=k)
{
if(k) k--;
j=sa[rank[i]-];
while(r[i+k]==r[j+k]) k++;
}
} void init()
{
memset(s,,sizeof(s));
memset(sa,,sizeof(sa));
memset(wa,,sizeof(wa));
memset(wb,,sizeof(wb));
memset(wc,,sizeof(wc));
memset(wd,,sizeof(wd));
memset(height,,sizeof(height));
memset(rank,,sizeof(rank));
} void solve(ll f,int L,int R)
{
//printf("%lld %d %d\n",f,L,R);
for(int i=L-;i<=R+;i++) H[i]=height[i];
for(int i=L;i<=R;i++) c[i]=d[i]=;
stk[]=L-; H[L-]=-oo;
int top=;
for(int i=L;i<=R;i++)
{
while(top&&H[i]<H[stk[top]]) top--;
if(stk[top]==L-) c[i]=L;
else c[i]=stk[top]+;
stk[++top]=i;
}
stk[]=R+; H[R+]=-oo;
top=;
for(int i=R;i>=L;i--)
{
while(top&&H[i]<=H[stk[top]]) top--;
if(stk[top]==R+) d[i]=R;
else d[i]=stk[top]-;
stk[++top]=i;
}
ll tmp=;
for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+)*(d[i]-i+)*height[i];
// printf("%lld\n",tmp);
ll t=R-L+;
tmp=tmp-K*(t+)*t/;
// printf("%lld\n",tmp);
for(int i=L;i<=R;i++) tmp=tmp+(-c[i]+i+)*(d[i]-i+);
// printf("%lld\n",tmp);
ans=ans+f*tmp;
} int main()
{
freopen("poj3415.in","r",stdin);
freopen("poj3415.out","w",stdout);
while(scanf("%lld",&K)!=EOF)
{
if(K==) break;
ans=;
init();
scanf("%s",a);
int n1=strlen(a);
scanf("%s",b);
int n2=strlen(b);
for(int i=;i<n1;i++)
if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+;
else s[i]=a[i]-'a'+;
s[n1]=;
n=n1;
getsa(s,sa,n+,);
getheight(s,sa,n); int i=;
while(i<n)
{
i++;
if(height[i]>=K)
{
int st=i;
while(i<=n&&height[i]>=K) i++;
if(st<=i-) solve(-,st,i-);
}
}
//printf("%lld\n",ans); init();
for(int i=;i<n2;i++)
if('A'<=b[i]&&b[i]<='Z') s[i]=b[i]-'A'+;
else s[i]=b[i]-'a'+;
s[n2]=;
n=n2;
getsa(s,sa,n+,);
getheight(s,sa,n);
i=;
while(i<n)
{
i++;
if(height[i]>=K)
{
int st=i;
while(i<=n&&height[i]>=K) i++;
if(st<=i-) solve(-,st,i-);
}
}
// printf("%lld\n",ans); init();
for(int i=;i<n1;i++)
if('A'<=a[i]&&a[i]<='Z') s[i]=a[i]-'A'+;
else s[i]=a[i]-'a'+;
s[n1]=;
for(int i=;i<n2;i++)
if('A'<=b[i]&&b[i]<='Z') s[n1+i+]=b[i]-'A'+;
else s[n1+i+]=b[i]-'a'+;
s[n1+n2+]=;
n=n1+n2+;
getsa(s,sa,n+,);
getheight(s,sa,n);
// for(int i=1;i<=n;i++) printf("%d\n",sa[i]);
i=;
while(i<n)
{
i++;
if(height[i]>=K)
{
int st=i;
while(i<=n&&height[i]>=K) i++;
if(st<=i-) solve(,st,i-);
}
}
//for(int i=0;i<=n1+n2;i++) printf("%d\n",sa[i]);
//for(int i=2;i<=n1+n2+2;i++) printf("%d\n",height[i]);
printf("%lld\n",ans);
}
return ;
}
【POJ3415】Common Substrings(后缀数组,单调栈)的更多相关文章
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- POJ3415 Common Substrings(后缀数组 单调栈)
借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...
- poj 3415 Common Substrings 后缀数组+单调栈
题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...
- poj 3415 Common Substrings——后缀数组+单调栈
题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...
- poj 3415 Common Substrings —— 后缀数组+单调栈
题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...
- poj3415 Common Substrings (后缀数组+单调队列)
Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 9414 Accepted: 3123 Description A sub ...
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
随机推荐
- 人人必知的10个 jQuery 小技巧
原文地址:http://info.9iphp.com/10-jquery-tips-everyone-should-know/ 人人必知的10个 jQuery 小技巧 收集的10个 jQuery ...
- 根据HTML语义化编码
语义化标签——http://www.html5jscss.com/html5-semantics-section.html 写HTML代码时应注意什么? 尽可能少的使用无语义的标签div和span: ...
- 利用python进行数据分析1_numpy的基本操作,建模基础
import numpy as np # 生成指定维度的随机多维数据 data=np.random.rand(2,3) print(data) print(type(data)) 结果: [[0.11 ...
- fckeditor配置详解
使用配置设置: . FCKConfig.CustomConfigurationsPath = '' ; // 自定义配置文件路径和名称 . FCKConfigFCKConfig.EditorAreaC ...
- shell脚本,awk 根据文件某列去重并且统计该列频次。
a文件为 a a a s s d .怎么把a文件变为 a s d .怎么把a文件变为 a a a s s d 解题方法如下: 解题思路 [root@localhost study]# awk 'NR= ...
- shell脚本,提示用户输入一个用户名,如果存在;显示用户UID和SHELL信息;否则,则显示无此用户;显示完成之后,提示用户再次输入;如果是quit则退出;
[root@localhost wyb]# cat tishiuser.sh #!/bin/bash #提示用户输入一个用户名,如果存在:显示用户UID和SHELL信息:否则, #则显示无此用户:显示 ...
- 将 PROTOCOL 的方法声明为 MUTATING
将 PROTOCOL 的方法声明为 MUTATING 由 王巍 (@ONEVCAT) 发布于 2014/08/17 Swift 的 protocol 不仅可以被 class 类型实现,也适用于 str ...
- 文件操作-cp
Linux cp命令 也是我们在实际使用中非常常用的一个命令,主要用来复制文件.文件夹等.今天就来给大家介绍下 cp命令 的使用. 转载自 https://www.linuxdaxue.com/lin ...
- GIMP做成颜色蒙板
效果图: 原始的美女图片上盖了一层的颜色,这个是想出来的效果,只是用来实践学到的技能,具体的场景还没有确定. 1/首先打开原始的美女图片: 2/然后在添加一张新的图片,作为新的图层添加进来: 这样的话 ...
- python爬虫入门七:pymysql库
我们使用python爬取得到的数据,有时候会数据量特别大,需要存入数据库. 需要注意的是,MySQL是一种关系型数据库管理系统,利用MySQL可以对数据库进行操作,而MySQL并不是一个数据库. 而p ...