bzoj3796Mushroom追妹纸

题目描述

Mushroom最近看上了一个漂亮妹纸。他选择一种非常经典的手段来表达自己的心意——写情书。考虑到自己的表达能力,Mushroom决定不手写情书。他从网上找到了两篇极佳的情书,打算选择其中共同的部分。另外,Mushroom还有个一个情敌Ertanis,此人也写了封情书给妹子。
Mushroom不希望自己的情书中完整的出现了情敌的情书。(这样抄袭的事情就暴露了)。
Mushroom把两封情书分别用字符串s1和s2来表示,Ertanis的情书用字符串s3来表示,他要截取的部分用字符串w表示。
需满足:
1、w是s1的子串
2、w是s2的子串
3、s3不是w的子串
4、w的长度应尽可能大
所谓子串是指:在字符串中连续的一段。
题解
我真是有看见字符串想SAM综合征。。
要求匹配的串只有两个,可以把它们连起来求一遍SA。
然后KMP求出c在大串中出现的位置。
维护一个数组f[i]表示从i位置开始至多延长多少个位置保证不包含c。
然后扫两遍,一遍算第一个串对第二个串的贡献,再算第二个串对第一个串的贡献,滚动维护一下min(height)就好了。
又TM开小数组了。、
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200009
using namespace std;
int n,m,sa[N],rnk[N],tong[N],y[N],height[N],n1,fail[N],f[N],ans;
bool b[N],tag[N];
char s[N],s1[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
m=;
for(int i=;i<=n;++i)rnk[i]=s[i],y[i]=i;
qsort();
for(int w=,p=;p<n;m=p,w<<=){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);rnk[sa[]]=p=;
for(int i=;i<=n;++i)rnk[sa[i]]=((y[sa[i]]==y[sa[i-]])&&(y[sa[i]+w]==y[sa[i-]+w]))?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(s[i+j]==s[sa[rnk[i]-]+j])j++;
height[rnk[i]]=j;
}
}
inline void check(int pos,int ln){
int j=;
for(int i=pos;i<=pos+ln-;++i){
while(j&&s[i]!=s1[j+])j=fail[j];
if(s[i]==s1[j+])j++;
if(j==n1){cout<<"gan";return;}
}
cout<<"yeah";
}
int main(){
scanf("%s%s",s+,s1+);
n=strlen(s+);n1=strlen(s1+);
for(int i=;i<=n;++i)f[i]=n-i+;s[++n]='#';
for(int i=;i<=n1;++i)s[++n]=s1[i],b[n]=,f[n]=n1-i+;
SA();
scanf("%s",s1+);n1=strlen(s1+);
int j=;
for(int i=;i<=n1;++i){
while(j&&s1[i]!=s1[j+])j=fail[j];
if(s1[i]==s1[j+])j++;fail[i]=j;
}
j=;
for(int i=;i<=n;++i){
while(j&&s[i]!=s1[j+])j=fail[j];
if(s[i]==s1[j+])j++;
if(j==n1)tag[i-j+]=;
}
int xian=n+;
for(int i=n;i>=;--i){
if(tag[i])xian=min(xian,i+n1-);
f[i]=min(f[i],xian-i);
}
xian=;
for(int i=;i<=n;++i){
int pos=sa[i];
if(!b[pos])xian=min(xian,height[i]),ans=max(ans,min(f[pos],xian));
else xian=2e9;
}
xian=;
for(int i=;i<=n;++i){
int pos=sa[i];
if(b[pos])xian=min(xian,height[i]),ans=max(ans,min(f[pos],xian));
else xian=2e9;
}
cout<<ans;
return ;
}
SA四连
bzoj1692队列变换
FJ打算带他的N(1 <= N <= 30,000)头奶牛去参加一年一度的“全美农场主大奖赛”。在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过。 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie、Sylvia、Dora,登记人员就把这支队伍登记为BSD)。登记结束后,组委会将所有队伍的登记名称按字典序升序排列,就得到了他们的出场顺序。 FJ最近有一大堆事情,因此他不打算在这个比赛上浪费过多的时间,也就是说,他想尽可能早地出场。于是,他打算把奶牛们预先设计好的队型重新调整一下。 FJ的调整方法是这样的:每次,他在原来队列的首端或是尾端牵出一头奶牛,把她安排到新队列的尾部,然后对剩余的奶牛队列重复以上的操作,直到所有奶牛都被插到了新的队列里。这样得到的队列,就是FJ拉去登记的最终的奶牛队列。 接下来的事情就交给你了:对于给定的奶牛们的初始位置,计算出按照FJ的调整规则所可能得到的字典序最小的队列。
每次只有两种选择,从前拿和从后拿,判断这个需要字典序,用后缀数组就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 210002
using namespace std;
int n,m,rnk[N],y[N],tong[N],sa[N],top;
char s[N],zh[N],c[];
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
m=;
for(int i=;i<=n;++i)rnk[i]=s[i],y[i]=i;
qsort();
for(int w=,p=;p<n;m=p,w<<=){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();
swap(rnk,y);
rnk[sa[]]=p=;
for(int i=;i<=n;++i)rnk[sa[i]]=((y[sa[i]]==y[sa[i-]])&&(y[sa[i]+w]==y[sa[i-]+w]))?p:++p;
}
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;++i)scanf("%s",c),s[i]=c[];
int zu=n;
s[++n]='#';
for(int i=zu;i>=;--i)s[++n]=s[i];
SA();
int p=,q=zu+,pp=,qq=zu,cnt=;
for(int i=;i<=zu;++i){
if(rnk[p]<rnk[q]){printf("%c",s[pp]);pp++;p++;}
else{printf("%c",s[qq]);qq--;q++;}
cnt++;if(cnt==)puts(""),cnt=;
}
return ;
}

牛奶模式Milk Patterns

农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。 John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。

SA完后用单调队列维护一下长度为k的最小值就可以了。

#include<iostream>
#include<cstdio>
#define N 100002
#define M 1000002
using namespace std;
int n,m,tong[M],sa[N],rnk[N],y[N],a[N],k,h,t,q[N],height[N],ans;
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
for(int i=;i<=n;++i)rnk[i]=a[i],y[i]=i;
qsort();
for(int w=,p=;p<n;w<<=,m=p){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);rnk[sa[]]=p=;
for(int i=;i<=n;++i)rnk[sa[i]]=(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+w]==y[sa[i]+w])?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(a[i+j]==a[sa[rnk[i]-]+j])j++;
height[rnk[i]]=j;
}
}
int main(){
n=rd();k=rd();k--;
for(int i=;i<=n;++i)a[i]=rd(),m=max(m,a[i]);
SA();h=;t=;
for(int i=;i<=n;++i){
while(h<=t&&q[h]<i-k+)h++;
while(h<=t&&height[i]<=height[q[t]])t--;
q[++t]=i;
if(i>=+k-)ans=max(ans,height[q[h]]);
}
cout<<ans;
return ;
}

bzoj2946[Poi2000]公共串

求n个串的最长公共子串。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 50002
using namespace std;
int n,m,tong[N],sa[N],rnk[N],y[N],height[N],ans,p[][N],len,tag[N],ji[],num;
char s[N],s1[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
m=;
for(int i=;i<=n;++i)rnk[i]=s[i],y[i]=i;
qsort();
for(int w=,p=;p<n;w<<=,m=p){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);rnk[sa[]]=p=;
for(int i=;i<=n;++i)rnk[sa[i]]=(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+w]==y[sa[i]+w])?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(s[i+j]==s[sa[rnk[i]-]+j])j++;
height[rnk[i]]=j;
p[][rnk[i]]=j;
}
for(int i=;(<<i)<=n;++i)
for(int j=;j+(<<i)-<=n;++j)p[i][j]=min(p[i-][j],p[i-][j+(<<i-)]);
}
inline int RMQ(int l,int r){
int x=log2(r-l+);
return min(p[x][l],p[x][r-(<<x)+]);
}
int main(){
num=rd();
for(int i=;i<=num;++i){
scanf("%s",s1+);len=strlen(s1+);
for(int j=;j<=len;++j)s[++n]=s1[j],tag[n]=i;s[++n]=i;
}
SA();
for(int i=;i<=n;++i){
int id=sa[i];
ji[tag[id]]=i;int nn=2e9;
for(int j=;j<=num;++j)nn=min(nn,ji[j]);
if(!nn)continue;
ans=max(ans,RMQ(nn+,i));
}
cout<<ans;
return ;
}

bzoj3230相似子串

我们可以维护一个数组sum表示前i名后缀能够产生的本质不同的子串。

然后确定第i个子串可以用二分。

求公共后缀那块可以搞一个反着的后缀数组。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 100002
#define pa pair<int,int>
#define mm make_pair
using namespace std;
typedef long long ll;
ll ans;
int n,m,tong[N],y[N],q;
inline ll rd(){
ll x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct suffixarray{
int sa[N],rnk[N],p[][N],height[N];
ll sum[N];
char s[N];
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void build(){
m=;
for(int i=;i<=n;++i)rnk[i]=s[i],y[i]=i;
qsort();
for(int w=,p=;p<n;w<<=,m=p){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);rnk[sa[]]=p=;
for(int i=;i<=n;++i)rnk[sa[i]]=(y[sa[i-]]==y[sa[i]]&&y[sa[i-]+w]==y[sa[i]+w])?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(s[i+j]==s[sa[rnk[i]-]+j])j++;
height[rnk[i]]=j;
p[][rnk[i]]=j;
}
for(int i=;(<<i)<=n;++i)
for(int j=;j+(<<i)-<=n;++j)p[i][j]=min(p[i-][j],p[i-][j+(<<i-)]);
for(int i=;i<=n;++i)sum[i]=sum[i-]+n-sa[i]+-height[i];
}
inline pa get(ll x){
int l=,r=n;ll ans1,ans2;
if(sum[n]<x)return mm(-,-);
while(l<=r){
int mid=(l+r)>>;
if(sum[mid]>=x){ans1=mid;ans2=n-sa[mid]+-(sum[mid]-x);r=mid-;}
else l=mid+;
}
return mm(ans1,ans2);
}
inline int RMQ(int l,int r){
if(l>r)return 2e9;
int lo=log2(r-l+);
return min(p[lo][l],p[lo][r-(<<lo)+]);
}
}sa1,sa2;
int main(){
n=rd();q=rd();
scanf("%s",sa1.s+);
for(int i=;i<=n;++i)sa2.s[i]=sa1.s[n-i+];
sa1.build();sa2.build();ll x,y;
while(q--){
x=rd();y=rd();ans=;
pa xx=sa1.get(x),yy=sa1.get(y);
if(yy.first<){printf("-1\n");continue;}
ll zz=sa1.RMQ(xx.first+,yy.first);//cout<<zz<<endl;
zz=min(zz,(ll)min(yy.second,xx.second));
ans+=zz*zz;
xx.first=sa2.rnk[n-sa1.sa[xx.first]+-xx.second];
yy.first=sa2.rnk[n-sa1.sa[yy.first]+-yy.second];
zz=sa2.RMQ(min(xx.first,yy.first)+,max(yy.first,xx.first));
zz=min(zz,(ll)min(yy.second,xx.second));
ans+=zz*zz;
printf("%lld\n",ans);
}
return ;
}

POJ1743Musical Them

给一个数串,求串内有最长的子串,它出现了不止一次且存在两次出现的位置不相交。
这道题的限制条件比较多,不好直接做,考虑答案具有单调性,可以选择二分答案。

然后扫一遍height数组,把height>=mid分成若干联通块,块内维护posmin和posmax,若posmax-posmin>=mid则找到一组合法解。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 20009
#define inf 2e9
using namespace std;
int n,m,tong[N],rnk[N],sa[N],a[N],y[N],height[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
m=;
for(int i=;i<=n;++i)rnk[i]=a[i],y[i]=i;
qsort();
for(int w=,p=;p<n;m=p,w<<=){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);
rnk[sa[]]=p=;
for(int i=;i<=n;++i)
rnk[sa[i]]=((y[sa[i]]==y[sa[i-]])&&(y[sa[i]+w]==y[sa[i-]+w]))?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(a[i+j]==a[sa[rnk[i]-]+j])++j;
height[rnk[i]]=j;
}
}
inline bool check(int mid){
int ma=-inf,mi=inf;
for(int i=;i<=n;++i){
if(height[i]<mid){
ma=-inf;mi=inf;
}
else{
ma=max(ma,sa[i]);mi=min(mi,sa[i]);
ma=max(ma,sa[i-]);mi=min(mi,sa[i-]);
if(ma-mi>=mid)return ;
}
}
return ;
}
int main(){
while(){
n=rd();if(!n)return ;
memset(a,,sizeof(a));
memset(rnk,,sizeof(rnk));
memset(sa,,sizeof(sa));
for(int i=;i<=n;++i)a[i]=rd();
for(int i=;i<n;++i)a[i]=a[i+]-a[i]+;a[n]=;
n--;
SA();
int l=,r=n,ans=-;
while(l<=r){
int mid=(l+r)>>;
if(check(mid))ans=mid,l=mid+;else r=mid-;
}
printf("%d\n",ans+);
}
return ;
}

POJ3145

给两个串,求这两个串大于k的公共子串数量。

这个和那道省选题(找相同字符)基本是一道题。

先求出height数组,然后维护一个单调上升的单调栈,维护一个num,一个cnt,统计答案就好了。

注意,在压栈时,压的是i-1而不是i。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 200002
using namespace std;
typedef long long ll;
int m,n,rnk[N],height[N],y[N],tong[N],tag[N],sa[N],k,n1,n2,top;
ll ans,num,st[N],cnt[N];
char s[N],s1[N],s2[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline void qsort(){
for(int i=;i<=m;++i)tong[i]=;
for(int i=;i<=n;++i)tong[rnk[i]]++;
for(int i=;i<=m;++i)tong[i]+=tong[i-];
for(int i=n;i>=;--i)sa[tong[rnk[y[i]]]--]=y[i];
}
inline void SA(){
m=;
for(int i=;i<=n;++i)rnk[i]=s[i],y[i]=i;
qsort();
for(int w=,p=;p<n;m=p,w<<=){
p=;
for(int i=n-w+;i<=n;++i)y[++p]=i;
for(int i=;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
qsort();swap(rnk,y);
rnk[sa[]]=p=;
for(int i=;i<=n;++i)
rnk[sa[i]]=((y[sa[i]]==y[sa[i-]])&&(y[sa[i]+w]==y[sa[i-]+w]))?p:++p;
}
for(int i=;i<=n;++i){
if(rnk[i]==)continue;
int j=max(,height[rnk[i-]]-);
while(s[i+j]==s[sa[rnk[i]-]+j])++j;
height[rnk[i]]=j;
}
}
int main(){
while(){
k=rd();if(!k)break;
scanf("%s%s",s1+,s2+);n1=strlen(s1+);n2=strlen(s2+);
for(int i=;i<=n1;++i)s[i]=s1[i],tag[i]=;
for(int i=;i<=n2;++i)s[n1++i]=s2[i],tag[n1++i]=;s[n1+]='&';
n=n1+n2+;s[n+]=;
memset(height,,sizeof(height));
SA();
for(int i=;i<=n;++i)height[i]-=k-;ans=top=;
top=num=;
for(int i=;i<=n;++i){
int ji=tag[sa[i-]]==?:;
while(top&&st[top]>=height[i])num-=st[top]*cnt[top],ji+=cnt[top],top--;
if(height[i]>)st[++top]=height[i],cnt[top]=ji;num+=cnt[top]*st[top];
if(tag[sa[i]]==)ans+=num;
}
top=num=;
for(int i=;i<=n;++i){
int ji=tag[sa[i-]]==?:;
while(top&&st[top]>=height[i])num-=st[top]*cnt[top],ji+=cnt[top],top--;
if(height[i]>)st[++top]=height[i],cnt[top]=ji;num+=cnt[top]*st[top];
if(tag[sa[i]]==)ans+=num;
}
printf("%lld\n",ans);
}
return ;
}

bzoj3796(后缀数组)(SA四连)的更多相关文章

  1. 后缀数组(SA)总结

    后缀数组(SA)总结 这个东西鸽了好久了,今天补一下 概念 后缀数组\(SA\)是什么东西? 它是记录一个字符串每个后缀的字典序的数组 \(sa[i]\):表示排名为\(i\)的后缀是哪一个. \(r ...

  2. 后缀数组SA学习笔记

    什么是后缀数组 后缀数组\(sa[i]\)表示字符串中字典序排名为\(i\)的后缀位置 \(rk[i]\)表示字符串中第\(i\)个后缀的字典序排名 举个例子: ababa a b a b a rk: ...

  3. 后缀数组SA入门(史上最晦涩难懂的讲解)

    参考资料:victorique的博客(有一点锅无伤大雅,记得看评论区),$wzz$ 课件(快去$ftp$%%%),$oi-wiki$以及某个人的帮助(万分感谢!) 首先还是要说一句:我不知道为什么我这 ...

  4. [笔记]后缀数组SA

    参考资料这次是真抄的: 1.后缀数组详解 2.后缀数组-学习笔记 3.后缀数组--处理字符串的有力工具 定义 \(SA\)排名为\(i\)的后缀的位置 \(rk\)位置为\(i\)的后缀的排名 \(t ...

  5. 【字符串】后缀数组SA

    后缀数组 概念 实际上就是将一个字符串的所有后缀按照字典序排序 得到了两个数组 \(sa[i]\) 和 \(rk[i]\),其中 \(sa[i]\) 表示排名为 i 的后缀,\(rk[i]\) 表示后 ...

  6. 浅谈后缀数组SA

    这篇博客不打算讲多么详细,网上关于后缀数组的blog比我讲的好多了,这一篇博客我是为自己加深印象写的. 给你们分享了那么多,容我自私一回吧~ 参考资料:这位dalao的blog 一.关于求Suffix ...

  7. 后缀数组SA

    复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...

  8. 洛谷2408不同字串个数/SPOJ 694/705 (后缀数组SA)

    真是一个三倍经验好题啊. 我们来观察这个题目,首先如果直接整体计算,怕是不太好计算. 首先,我们可以将每个子串都看成一个后缀的的前缀.那我们就可以考虑一个一个后缀来计算了. 为了方便起见,我们选择按照 ...

  9. 洛谷4248 AHOI2013差异 (后缀数组SA+单调栈)

    补博客! 首先我们观察题目中给的那个求\(ans\)的方法,其实前两项没什么用处,直接\(for\)一遍就求得了 for (int i=1;i<=n;i++) ans=ans+i*(n-1); ...

随机推荐

  1. 简述HTTP协议

    引言 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网服务器传输超文本到本地浏览器的传送协议.HTTP 是基于 TCP/IP 协议通信协议 ...

  2. 搞站思路 <陆续完善中>

    只提供思路经验分享.不提供日站方法....一般站点那里最容易出现问题 入手思路: 主站一般都很安全.一般从二级域名下手 多看看那些大站新出来的测试分站点 猜路径别忘了google 考虑看站点下的rob ...

  3. js-XMLHttpRequest 2级

    ###1. XMLHttpRquest 2级 1)   FormData 现代web应用中频繁使用的一项功能就死表单数据的序列化, XMLHttpRquest 2级为此定义了FormData类型 Fo ...

  4. React-Native之截图组件view-shot的介绍与使用

    React-Native之截图组件view-shot的介绍与使用 一,需求分析 1,需要将分享页生成图片,并分享到微信好友与朋友圈. 二,react-native-view-shot介绍 1,可以截取 ...

  5. laravel 项目表单中有csrf_token,但一直报错419错误 解决redis连接错误:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persi

    laravel 项目表单中有csrf_token,但一直报错419错误,因为项目中使用到Redis缓存,在强制关闭Redis后出现的问题,查询laravel.log文件查找相关问题 安装redis后在 ...

  6. 10分钟让你的代码更加pythonic

    参考: https://blog.csdn.net/g8433373/article/details/80709116

  7. yield send 的一些使用细节

    其实日常中我们使用最多的是 return 很少会使用到 yield 去创造一个生成器.一般就是算算算 算完之后用 return 返回一把. 但是有些情况下 比如需要节约内存不需要一把全部返回,每次使用 ...

  8. ansible的playbook简单使用

    一.介绍 playbook就是一个用yaml语法把多个模块堆起来的一个文件 核心组件: Hosts:执行的远程主机列表Tasks:任务,由模块定义的操作的列表:Varniables:内置变量或自定义变 ...

  9. dede:field name=’position’标签调用 主页改成英文Home和改变符号

    在用dede:field name=’position’ 这个标签的时候我们调用的这个就是中文的,出现的是主页>+相应的栏目  ,那么这个问题怎么改成英文的呢?有好多大虾都说找到dede安装目录 ...

  10. python设计模式第八天【装饰器模式】

    1.定义 使用包装的释放扩展类的功能,但是不使用继承 2.使用场景 3.代码实现 #!/usr/bin/env python #! _*_ coding:UTF-8 _*_ def MyDecorat ...