首页 > 编程知识 正文

566988,hdu2063

时间:2023-05-05 12:29:50 阅读:173119 作者:3909

主题: problem-6988(dingbacode.com) )。

赋予一个字符串和每个字符的权重,求出本质不同的所有子字符串中第k个小字符串的权重。 字符串的权重是字符权重之和。

意识到必须考虑所有子串的情况,不能从中选择第k个小答案。 因此,为了得到结果,考虑用数据结构保存,或者迅速列举所有情况。 因为知道所有后缀的所有前缀都是所有子字符串的情况,所以通过枚举每个后缀的所有前缀可以期待结果。 但是,暴力列举绝对会超时,届时需要用于处理的数据结构。

首先要明确一点,从所有情况中选择第k个小答案的做法会超时。 由于情况非常多,各情况之间的大小关系不明确,所以要得到排序后的所有子序列的大小关系非常困难,需要花费时间。 注意到问题是输出结果这个唯一的数字,每个后缀的前缀的权重和长度都满足单调的关系,直接将答案平分列举,试图验证其正确性。

以下,考虑如何二分,确定下界为1,上界为原来的总串。 每次都计算中值mid,判断答案是在mid之前还是之后。 在答案为mid情况下,子串的权重小于不大于mid的数量的k意味着mid小; 否则,表示答案=mid,进一步缩小范围。

然后,求出子列的权重如何小于等于mid的数量。 对于每个后缀,前缀越长,权重就越大,因此可以在另二分钟内找到第一个权重大于mid的前缀。 假设当前后缀的开始位置为I,并且此后缀的第一个权重大于mid的前缀的末尾为j,则此后缀对当前枚举的答案的贡献前缀数为[j-1]-I1。 但是,请注意不同后缀的前缀可能是相同的,知道不同后缀的公共前缀(LCP )并加重回答。 到此为止可以用后缀数组处理。 通过按后缀的顺序列举后缀,可以通过height数组了解当前字符串和前一个字符串的重复前缀。 就这样减法就行了。

有关什么是后缀数组的信息,请参见此-后缀数组详细信息- chr ety-Blogs.com

很会说话,居然能让我看会议。

代码:

#includeiostream

using namespace std;

typedef long long int ll;

ll ran[100005]、sec[100005]、sa[100005]、t[100005]、hei[100005];

ll val[26],sum[100005];

char s[100005];

voidGetsa(lln )。

{

ll num,I,len,cnt;

num=26;

for(I=0; i=100000; I ) t(I )=0;

for(I=1; i=n; I ) ran(I )=s(I-1 )-a ) 1,t ) ran ) );

for(I=1; i=num; I ) t(I )=t(I-1 );

for(I=n; i=1; I----sa[t[ran[I]]----]=I;

for(len=1; len=n; len=1)

{

cnt=0;

for(I=n-len1; i=n; I ) sec[ cnt]=i;

for(I=1; i=n; I ) if(sa[I]len ) sec[ cnt]=sa[i] - len;

for(I=0; i=num; I ) t(I )=0;

for(I=1; i=n; I ) t[ran[i]];

for(I=1; i=num; I ) t(I )=t(I-1 );

for(I=n; i=1; I----sa[t[ran[sec[I]]--]=sec[I],sec[i]=ran[i];

ran[sa[1]]=1; cnt=1;

for(I=2; i=n; I )

ran [ sa [ I ]=[ sec [ sa [ I ]==sec [ sa [ I-1 ] ] sec [ sa [ I ] len ]==sec [ sa [ I-1 ] len ]? cnt : cnt;

if(CNT==n ) break;

num=cnt;

}

}

语音获取(lln ) )。

{

ll i,j,k;

k=0;

for(I=1; i=n; I )

{

if(k ) k----;

j=sa[ran[i] - 1];

while(Ik=njk=ns[I-1k]==s[j-1k] ) k;

hei[ran[i]]=k;

}

}

llcheck(llx,ll n ) ) ) ) ) ) ) llcheck(llx,ll n ) ) ) ) ) ) )。

{

ll ans=0,I;

ll,r,mid,add;

for(I=1; i=n; I )

{

l=sa[i]; r=n 1; add=-1;

wile(LR ) )。

{

mid=(LR ) 1;

if(sum[mid]-sum[sa[I]-1]=x ) l=mid 1,add=mid;

else r=mid;

}

if (添加!=-1 )

{

ans =add - sa[i] 1;

ans -=add - sa[i] 1 hei[i]? hei[i] : add - sa[i] 1;

}

}

返回ans;

}

int main () )

{

LTT,n,I,k,ans,l,r,mid;

cin tt;

while(TT----

{

scanf('%lld%lld )、n、k );

scanf('%s ',s );

for(I=0; i 26; I ) scanf('%lld ',val[i];

GETSA(n;

GETH(n;

sum[0]=0;

for(I=1; i=n; I ) sum[i]=val[s[i - 1] - 'a'] sum[i - 1];

l=1; r=sum[n] 1; ans=-1;

wile(LR ) )。

{

mid=(LR ) 1;

if(check(mid,n )=k ) r=mid,ans=mid;

else l=mid 1;

}

printf(%lld(n ),ans );

}

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。

  •  标签:  
  • 相关阅读