[Educational Round 5][Codeforces 616F. Expensive Strings]

这题调得我心疲力竭...Educational Round 5就过一段时间再发了_(:з」∠)_

先后找了三份AC代码对拍,结果有两份都会在某些数据上出点问题...这场的数据有点水啊_(:з」∠)_【然而卡掉本弱还是轻轻松松的】

题目链接:616F - Expensive Strings

题目大意:给出\(n\)个字符串\(t_i\)以及\(n\)个数\(c_i\),定义\(p_{s,i}\)为字符串\(s\)在\(t_i\)中出现的次数,\(f(s)=\sum_{i=1}^{n}c_i\cdot p_{s,i}\cdot |s|\),求\(f(s)\)的最大值

题解:考虑将\(n\)个字符串用互不相同的字符串连接起来,并求出新串的后缀数组。对于一段连续且合法(对任意i,有sa[i]对应的字符不为连接符)的区间\([l,r]\),其对应的答案就为\(min\left \{ height_i \right \}\cdot \sum c_j\),\(j\)为sa[i]所属原字符串的编号,对应所取的字符串就是这连续几个后缀的最长公共子串。因此若考虑暴力枚举所有的合法区间,会有下面的代码

for(int l=1;l<=len_sum;l++)if(s[sa[l]-1]>N)
      for(int r=l;r<=len_sum;r++)if(s[sa[r]-1]<N)break;else
        {
        LL k=0;
        int mi=N;
        for(int i=l+1;i<=r;i++)mi=min(mi,height[i]);
        if(mi==0)break;
        if(mi==N)
          {
          mi=0;
          for(int i=sa[l]-1;s[i]>N;i++)
            mi++;
          }
        for(int i=l;i<=r;i++)k+=1ll*mi*c[belong[sa[i]-1]];
        ans=max(ans,k);
        }
暴力

   但是这样是显然会TLE的,所以需要进一步优化

   考虑每一个height[i]的影响范围,即在该范围内,所有包含i的区间都以height[i]为最小值,此时原式的式子就为\(height_i\cdot \sum_{i=l}^{r}c_j\),这里\(l\),\(r\)表示的就是height[i]的影响范围,\(j\)依然为sa[i]所属原字符串的编号。预处理每个height[i]的影响范围以及\(c_j\)的前缀和就好了

#include<bits/stdc++.h>
using namespace std;
#define N 600001
#define LL long long
int wa[N+1001],wb[N+1001],wv[N+1001],Ws[N+1001];
int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(const int r[],int sa[],int n,int m)
{
      int i,j,p,*x=wa,*y=wb,*t; 
      for(i=0; i<m; i++) Ws[i]=0;
      for(i=0; i<n; i++) Ws[x[i]=r[i]]++;
      for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
      for(i=n-1; i>=0; i--) sa[--Ws[x[i]]]=i;
      for(j=1,p=1; p<n; j*=2,m=p)
      {
            for(p=0,i=n-j; i<n; i++) y[p++]=i; 
            for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0; i<n; i++) wv[i]=x[y[i]];
            for(i=0; i<m; i++) Ws[i]=0;
            for(i=0; i<n; i++) Ws[wv[i]]++;
            for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
            for(i=n-1; i>=0; i--) sa[--Ws[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
                  x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
      }
      return;
}
int sa[N],Rank[N],height[N];
void calheight(const int *r,int *sa,int n)
{
      int i,j,k=0;
      for(i=1; i<=n; i++) Rank[sa[i]]=i;
      for(i=0; i<n; height[Rank[i++]]=k)
            for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);
      for(int i=n;i>=1;--i) ++sa[i],Rank[i]=Rank[i-1];
}
char str[N];
LL ans,sum[N];
int n,c[N],s[N],leng[N],belong[N],_l[N],_r[N],len_sum;
void rua(int L,int R)
{
    LL res=0,x,le;
    for(int i=L;i<=R;i++)
      {
      x=belong[sa[i]-1];
      le=leng[x]-sa[i]+1;
      if((i==R || height[i+1]<le) && (i==L || height[i]<le))
        res=max(res,1ll*le*c[x]);
      }
    for(int i=L;i<=R;i++)
      res=max(res,1ll*height[i]*(sum[min(R,_r[i])]-sum[max(L,_l[i]-1)-1]));
    ans=max(ans,res);
}
int main()
{
    scanf("%d",&n);
    scanf("%s",str);
    int len=strlen(str);
    for(int i=0;i<len;i++)
      belong[len_sum]=1,s[len_sum++]=str[i]+N;
    leng[1]=len_sum;
    for(int i=2;i<=n;i++)
      {
      s[len_sum++]=i;
      scanf("%s",str);
      len=strlen(str);
      for(int j=0;j<len;j++)
        belong[len_sum]=i,s[len_sum++]=str[j]+N;
      leng[i]=len_sum;
      }
    da(s,sa,len_sum+1,N+1000);
    calheight(s,sa,len_sum);
    for(int i=1;i<=n;i++)
      scanf("%d",&c[i]);
    for(int i=1;i<=len_sum;i++)
      sum[i]=sum[i-1]+c[belong[sa[i]-1]];
    _l[1]=1,_r[len_sum]=len_sum;
    for(int i=2;i<=len_sum;i++)
      {
      int _=i;
      while(_>1 && height[i]<=height[_-1])
        _=_l[_-1];
      _l[i]=_;
      }
    for(int i=len_sum-1;i>=1;i--)
      {
      int _=i;
      while(_<len_sum && height[i]<=height[_+1])
        _=_r[_+1];
      _r[i]=_;
      }
    for(int l=1;l<=len_sum;l++)if(s[sa[l]-1]>N)
      {
      int r=l;
      while(r<=len_sum && s[sa[r]-1]>N)r++;
      rua(l,r-1);
      l=r;
      }
    printf("%I64d\n",ans);
}
View Code

 

转载于:https://www.cnblogs.com/DeaphetS/p/9665970.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值