【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\)就可以了. 对于相同子串,我们能想 ...
随机推荐
- OpenGL 渲染上下文-context
context理解 OpenGL在渲染的时候需要一个Context,这个Context记录了OpenGL渲染需要的所有信息,可以把它理解成一个大的结构体,它里面记录了当前绘制使用的颜色.是否有光照计算 ...
- android 焦点 ListView 点击事件获取失败
1. 在ListView 中, 创建一个app_item.xml 布局文件 在布局文件中有如下的代码: <CheckBox android:id="@+id/cb_t ...
- CSS3与弹性盒布局
1.弹性盒布局对齐模式 1.1.弹性盒子 在规定弹性盒子之中的子级元素换行显示之前父级元素必须是弹性盒子模型,也就是设置 display 为 flex 代码如下: <!DOCTYPE html& ...
- plsql循环的简单实例
declare v_id tbl_regions.regions_id%type; begin .. loop select t.regions_id into v_id from tbl_regio ...
- Protocol(协议)、Delegate(委托)、DataSource(数据源)
这里以 UITableViewController 和 UITableView 的关系为例: //--------------------------------------------------- ...
- ios之UISearchBar
当你在seachBar中输入字母之前的时候,只是用鼠标选中searchBar的时候,如图 终端输出截图如下:(这个时候调用先shouldBeginEditing,之后调用didBeginEditing ...
- 总结:JavaScript异步、事件循环与消息队列、微任务与宏任务
本人正在努力学习前端,内容仅供参考.由于各种原因(不喜欢博客园的UI),大家可以移步我的github阅读体验更佳:传送门,喜欢就点个star咯,或者我的博客:https://blog.tangzhen ...
- 洛谷 P2872 道路建设
https://www.luogu.org/problemnew/show/P2872 算是比较裸的并查集了,已经有路的两个点之间建一条代价为0的边,路径长度计算两点之间的距离,做并查集就好咯. #i ...
- 牛客练习赛40 C-小A与欧拉路
求图中最短的欧拉路.题解:因为是一棵树,因此当从某一个节点遍历其子树的时候,如果还没有遍历完整个树,一定还需要再回到这个节点再去遍历其它子树,因此除了从起点到终点之间的路,其它路都被走了两次,而我们要 ...
- Day16模块
Day16 当做执行文件时 __name__ = "__main__" 当做模块被导入时 __name__ 等于文件名即模块名 ```python 循环导入(模块的名称空间已经建立 ...