您的位置:首页 > 其它

【NOI2015】品酒大会

2017-02-06 21:01 393 查看
令${str\left(i,j \right)}$为区间${[l,r]}$所表示的子串。

对于任意$r$

一,求${\sum _{i=1}^{n}\sum _{j=i+1}^{n}[str(i,i+r-1)=str(j,j+r-1)]}$

二,求${ans[r]=max(val[i]*val[j])}$,且${str(i,i+r-1)=str(j,j+r-1)}$

  直接用SAM构出后缀树,然后一个子串一定是原串的一个后缀的前缀,然后找到后缀树中每一个后缀对应的节点,每一对后缀的LCP对应了后缀树中的相应点的LCA的len(即代表的最长串的长度),然后做一遍树形统计统计第一问答案,第二问答案即要记一下子树最大值最小值即可。

  

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define maxn 1000100
#define llg long long
#define SIZE 26
#define inf (((llg)1e18)+10)
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
llg n,m,ans1[maxn<<1],ans2[maxn<<1],val[maxn],zhu[maxn<<1],quan[maxn<<1],tail;
llg minl[maxn<<1],maxl[maxn<<1],ans3[maxn<<1];
char s[maxn];

struct SAM
{
struct
{
llg len,f,ch[SIZE];
void init()
{
len=0,f=-1;
memset(ch,0xff,sizeof(ch));
}
}e[maxn<<1];

vector<llg>a[maxn<<1];
llg idx,last,size[maxn<<1];

void init(){idx=last=0; e[idx++].init(); memset(size,0,sizeof(size)); }

llg newnode(){e[idx].init(); return idx++;}

void insert(llg c)
{
llg end=newnode(),tmp=last;
e[end].len=e[last].len+1; size[end]=1; zhu[end]=1; quan[end]=val[tail]; maxl[end]=val[tail],minl[end]=val[tail]; tail++;
for (;tmp!=-1 && e[tmp].ch[c]==-1;tmp=e[tmp].f)
e[tmp].ch[c]=end;
if (tmp==-1) e[end].f=0;
else
{
llg nxt=e[tmp].ch[c];
if (e[tmp].len+1==e[nxt].len) e[end].f=nxt;
else
{
llg np=newnode();// maxl[np]=maxl[end],minl[np]=minl[end];
e[np]=e[nxt];
e[np].len=e[tmp].len+1;
e[nxt].f=e[end].f=np;
for (;tmp!=-1 && e[tmp].ch[c]==nxt;tmp=e[tmp].f) {e[tmp].ch[c]=np;}
}
}
last=end;
//    cout<<last<<endl;
}

void link_fa() {for (llg i=1;i<idx;i++) a[e[i].f].push_back(i);}

void dp(llg x)
{
llg w=a[x].size(),v;
for (llg i=0;i<w;i++) dp(a[x][i]);
for (llg i=0;i<w;i++)
{
v=a[x][i];
ans1[e[x].len]+=size[x]*size[v];
if (1)
{
if (maxl[v]!=-1*inf)
{
if (maxl[x]!=-1*inf) ans2[e[x].len]=max(ans2[e[x].len],maxl[x]*maxl[v]);
maxl[x]=max(maxl[x],maxl[v]);
}
if (minl[v]!=inf)
{
if (minl[x]!=inf) ans2[e[x].len]=max(ans2[e[x].len],minl[x]*minl[v]);
minl[x]=min(minl[x],minl[v]);
}
}
size[x]+=size[v];
}
//ans1[e[x].len]+=size[x];
}
}sam;

int main()
{
yyj("a");
cin>>n;
sam.init();
scanf("%s",s);
for (llg i=0;i<=n*2;i++) ans2[i]=maxl[i]=-1*inf,minl[i]=inf,ans3[i]=inf*-1;
for (llg i=0;i<n;i++) scanf("%lld",&val[i]);
for (llg i=0;i<(n+1)/2;i++) swap(val[i],val[n-i-1]);
for (llg i=n-1;i>=0;i--)
sam.insert(s[i]-'a');
sam.link_fa();
sam.dp(0);
for (llg i=n-1;i>=1;i--)
{
ans1[i-1]+=ans1[i];
if (ans1[i]) ans2[i-1]=max(ans2[i-1],ans2[i]);
}
//    for (llg i=0;i<n;i++) ans3[sam.e[i].len]=max(ans3[sam.e[i].len],ans2[i]);
for (llg i=0;i<n;i++) printf("%lld %lld\n",ans1[i],ans1[i]?ans2[i]:0);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: