博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ.3145.Common Substrings(后缀数组 倍增 单调栈)
阅读量:4349 次
发布时间:2019-06-07

本文共 2381 字,大约阅读时间需要 7 分钟。

\(Description\)

求两个字符串长度不小于k的公共子串对数。

\(Solution\)

求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}(A'到B'ht[]的最小值)。

维护一个栈,栈中ht从底到顶递减。
如果当前是求B中后缀i和前边A中子串的答案,那么记录之前的∑(ht(A)),这就是前边A对i的贡献。
然后更新这个栈,若ht[i]>ht[top],入栈即可 但不对B计算答案;
若ht[i]<=ht[top],因为公共子串是min{ht()},i入栈后要对所有ht[top-1]>=ht[i]的top-1改成ht[i],并且i出栈(期间减去当前多算的答案ht[top]-ht[top-1]),直到ht[top-1]<ht[top]

//6096K 704MS#include 
#include
#include
typedef long long LL;const int N=2e5+10;int n,sa[N],ht[N],rk[N],sa2[N],tm[N],sk[N],val[N],bel[N];char s[N];void Get_SA(){ int *x=rk,*y=sa2,m=260; for(int i=0; i<=m; ++i) tm[i]=0; for(int i=1; i<=n; ++i) ++tm[x[i]=s[i]+1]; for(int i=1; i<=m; ++i) tm[i]+=tm[i-1]; for(int i=n; i; --i) sa[tm[x[i]]--]=i; for(int p=0,k=1; k
k) y[++p]=sa[i]-k; for(int i=0; i<=m; ++i) tm[i]=0; for(int i=1; i<=n; ++i) ++tm[x[i]]; for(int i=1; i<=m; ++i) tm[i]+=tm[i-1]; for(int i=n; i; --i) sa[tm[x[y[i]]]--]=y[i]; std::swap(x,y), p=x[sa[1]]=1; for(int i=2; i<=n; ++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p:++p; if(p>=n) break; } for(int i=1; i<=n; ++i) rk[sa[i]]=i; ht[1]=0; for(int k=0,p,i=1; i<=n; ++i) { if(rk[i]==1) continue; if(k) --k; p=sa[rk[i]-1]; while(i+k<=n&&p+k<=n&&s[i+k]==s[p+k]) ++k; ht[rk[i]]=k; }}int main(){ int k; while(scanf("%d",&k),k) { scanf("%s",s+1); int l=strlen(s+1); s[l+1]=1, scanf("%s",s+2+l), n=strlen(s+1); Get_SA(); for(int i=2/*1*/; i<=n; ++i) { ht[i]-=k-1, bel[i]=sa[i]>l; if(ht[i]<0) ht[i]=0; } LL res=0,tmp; val[0]=-1; for(int top,t=0; t<=1; ++t) { tmp=0, top=0; for(int i=2/*1*/; i<=n; ++i)//ht[1]就是补充字符 计算不计算都行 { if(bel[i]!=t) res+=tmp; sk[++top]=bel[i]==t; val[top]=ht[i+1]; tmp+=(LL)sk[top]*val[top]; while(val[top-1]>=val[top]) { --top; tmp-=(LL)(val[top]-val[top+1])*sk[top];//减去之前多余的贡献 val[top]=val[top+1], sk[top]+=sk[top+1]; } } } printf("%lld\n",res); } return 0;}

转载于:https://www.cnblogs.com/SovietPower/p/8570413.html

你可能感兴趣的文章
vue+element前端自行分页
查看>>
C#操作XML
查看>>
tkinter学习02
查看>>
Mapnik使用postgres中的栅格数据
查看>>
html基本知识
查看>>
IOS手势不识别
查看>>
IOS网络编程之请求内容
查看>>
爬虫——为什么有代理
查看>>
HDU 1599 find the mincost route(floyd求最小环 无向图)
查看>>
vue v-for循环checkbox存在的问题
查看>>
hibernate模糊查询-Restrictions.ilike & Expression.like
查看>>
二分·归并排序之逆序对 算法讲解和题目
查看>>
python @property
查看>>
J2SE基础夯实系列之String字符串不可变的理解,不可变类,final关键字到底修饰了什么...
查看>>
2.7 UML状态图
查看>>
【linux】记录一下遇到的各种问题
查看>>
python学习之day4,函数
查看>>
Java学习之异常处理
查看>>
使用Maven命令安装jar包到仓库中
查看>>
JavaScript 数据类型
查看>>