首页 > 代码库 > 【NOI2015】品酒大会
【NOI2015】品酒大会
令${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(即代表的最长串的长度),然后做一遍树形统计统计第一问答案,第二问答案即要记一下子树最大值最小值即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 1000100 10 #define llg long long 11 #define SIZE 26 12 #define inf (((llg)1e18)+10) 13 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 14 llg n,m,ans1[maxn<<1],ans2[maxn<<1],val[maxn],zhu[maxn<<1],quan[maxn<<1],tail; 15 llg minl[maxn<<1],maxl[maxn<<1],ans3[maxn<<1]; 16 char s[maxn]; 17 18 struct SAM 19 { 20 struct 21 { 22 llg len,f,ch[SIZE]; 23 void init() 24 { 25 len=0,f=-1; 26 memset(ch,0xff,sizeof(ch)); 27 } 28 }e[maxn<<1]; 29 30 vector<llg>a[maxn<<1]; 31 llg idx,last,size[maxn<<1]; 32 33 void init(){idx=last=0; e[idx++].init(); memset(size,0,sizeof(size)); } 34 35 llg newnode(){e[idx].init(); return idx++;} 36 37 void insert(llg c) 38 { 39 llg end=newnode(),tmp=last; 40 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++; 41 for (;tmp!=-1 && e[tmp].ch[c]==-1;tmp=e[tmp].f) 42 e[tmp].ch[c]=end; 43 if (tmp==-1) e[end].f=0; 44 else 45 { 46 llg nxt=e[tmp].ch[c]; 47 if (e[tmp].len+1==e[nxt].len) e[end].f=nxt; 48 else 49 { 50 llg np=newnode();// maxl[np]=maxl[end],minl[np]=minl[end]; 51 e[np]=e[nxt]; 52 e[np].len=e[tmp].len+1; 53 e[nxt].f=e[end].f=np; 54 for (;tmp!=-1 && e[tmp].ch[c]==nxt;tmp=e[tmp].f) {e[tmp].ch[c]=np;} 55 } 56 } 57 last=end; 58 // cout<<last<<endl; 59 } 60 61 void link_fa() {for (llg i=1;i<idx;i++) a[e[i].f].push_back(i);} 62 63 void dp(llg x) 64 { 65 llg w=a[x].size(),v; 66 for (llg i=0;i<w;i++) dp(a[x][i]); 67 for (llg i=0;i<w;i++) 68 { 69 v=a[x][i]; 70 ans1[e[x].len]+=size[x]*size[v]; 71 if (1) 72 { 73 if (maxl[v]!=-1*inf) 74 { 75 if (maxl[x]!=-1*inf) ans2[e[x].len]=max(ans2[e[x].len],maxl[x]*maxl[v]); 76 maxl[x]=max(maxl[x],maxl[v]); 77 } 78 if (minl[v]!=inf) 79 { 80 if (minl[x]!=inf) ans2[e[x].len]=max(ans2[e[x].len],minl[x]*minl[v]); 81 minl[x]=min(minl[x],minl[v]); 82 } 83 } 84 size[x]+=size[v]; 85 } 86 //ans1[e[x].len]+=size[x]; 87 } 88 }sam; 89 90 int main() 91 { 92 yyj("a"); 93 cin>>n; 94 sam.init(); 95 scanf("%s",s); 96 for (llg i=0;i<=n*2;i++) ans2[i]=maxl[i]=-1*inf,minl[i]=inf,ans3[i]=inf*-1; 97 for (llg i=0;i<n;i++) scanf("%lld",&val[i]); 98 for (llg i=0;i<(n+1)/2;i++) swap(val[i],val[n-i-1]); 99 for (llg i=n-1;i>=0;i--) 100 sam.insert(s[i]-‘a‘);101 sam.link_fa();102 sam.dp(0);103 for (llg i=n-1;i>=1;i--) 104 {105 ans1[i-1]+=ans1[i];106 if (ans1[i]) ans2[i-1]=max(ans2[i-1],ans2[i]);107 }108 // for (llg i=0;i<n;i++) ans3[sam.e[i].len]=max(ans3[sam.e[i].len],ans2[i]);109 for (llg i=0;i<n;i++) printf("%lld %lld\n",ans1[i],ans1[i]?ans2[i]:0);110 return 0;111 }
【NOI2015】品酒大会
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。