题意:

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(后缀数组,单调栈)的更多相关文章

  1. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  2. POJ3415 Common Substrings(后缀数组 单调栈)

    借用罗穗骞论文中的讲解: 计算A 的所有后缀和B 的所有后缀之间的最长公共前缀的长度,把最长公共前缀长度不小于k 的部分全部加起来.先将两个字符串连起来,中间用一个没有出现过的字符隔开.按height ...

  3. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  4. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  5. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  6. poj3415 Common Substrings (后缀数组+单调队列)

    Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 9414   Accepted: 3123 Description A sub ...

  7. 【BZOJ-3238】差异 后缀数组 + 单调栈

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status] ...

  8. BZOJ_3879_SvT_后缀数组+单调栈

    BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...

  9. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  10. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

随机推荐

  1. fluent_python2

    字典和集合 泛映射类型, 继承自collections.abc, Mapping和MutableMapping 标准库里的所有映射类型都是利用 dict 来实现的,因此它们有个共同的限制,即只有可散列 ...

  2. 一、submit和button区别

    一.submit和button区别 一.HTTP方法:GET.POST

  3. Python 类变量,成员变量,静态变量,局部变量

    局部 class TestClass(object): val1 = 100 def __init__(self): self.val2 = 200 def fcn(self,val = 400): ...

  4. nyoj-47-过河问题|POJ-1700-Crossing River

    http://acm.nyist.net/JudgeOnline/problem.php?pid=47 http://poj.org/problem?id=1700 解题思路:求最少需要多少时间才能都 ...

  5. C++ _ const的用法,特别是用在函数前面与后面的区别!

    在普通的非 const成员函数中 this的类型是一个指向类类型的 const指针.可以改变this所指向的值,但不能改变 this所保存的地址. 在 const成员函数中 this的类型是一个指向 ...

  6. Codeforces 727C Guess the Array

    题目传送门 长度为\(n\)的数组,询问\(n\)次来求出数组中每一个数的值 我们可以先询问三次 \(a[1]+a[2]\) \(a[1]+a[3]\) \(a[2]+a[3]\) 然后根据这三次询问 ...

  7. shell脚本,计算1+3+5....100等于多少?

    [root@localhost wyb]# cat unevenjia.sh #!/bin/bash #从1+++...100的结果 i= count=$1 $count` do sum=$(($su ...

  8. div section article区分--20150227

    div section article ,语义是从无到有,逐渐增强的.div 无任何语义,仅仅用作样式化或者脚本化的钩子(hook),对于一段主题性的内容,则就适用 section,而假如这段内容可以 ...

  9. (52)zabbix_sender提交item数据

    zabbix_sender是什么?有什么作用 zabbix获取key值有超时时间,如果自定义的key脚本一般需要执行很长时间,这根本没法去做监控,那怎么办呢?使用zabbix监控类型zabbix tr ...

  10. perl学习之:正则表达式