【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(即代表的最长串的长度),然后做一遍树形统计统计第一问答案,第二问答案即要记一下子树最大值最小值即可。
对于任意$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; }
相关文章推荐
- [BZOJ]4199 品酒大会(Noi2015)
- 【NOI2015】bzoj4199 品酒大会【解法二】
- 【BZOJ4199】【NOI2015】品酒大会(后缀数组)
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
- NOI 2015 品酒大会
- NOI2015品酒大会 后缀数组
- 【BZOJ4199】【NOI2015】品酒大会(后缀数组)
- BZOJ4199:[NOI2015]品酒大会——题解
- [BZOJ4199][Noi2015]品酒大会(后缀数组+并查集)
- 【NOI2015】品酒大会
- bzoj4199 [Noi2015]品酒大会
- Bzoj4199:[NOI2015]品酒大会
- bzoj4199&&luogu2178 noi2015品酒大会 后缀数组
- BZOJ_4199_[Noi2015]品酒大会_后缀自动机
- BZOJ4199 [Noi2015]品酒大会
- 【bzoj4199】[Noi2015]品酒大会 后缀自动机
- Bzoj4199:[NOI2015]品酒大会
- 【NOI2015】品酒大会
- 洛谷 P2178 品酒大会(bzoj P4199 [Noi2015]品酒大会/uoj P131【NOI2015】品酒大会)
- [bzoj4199][NOI2015]品酒大会