• [loj3049]字符串问题


    考虑将所有A串向所能支配的B串连边,B串向满足B串是A串前缀的A串连边,在A串上有点权,跑最长路即可
    但这样前缀的边太多,考虑优化:在后缀树上,将这些串插入进去(注意相同的串A串要在B串下面),并将父亲向儿子连边,那么相当于实现了上面的问题
    但这样还有一个问题:需要将所有A串裂为两个点,因为并不是经过A串就一定可以有收益,而是要选择A串(即走A串连向B串的边)才有收益

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 1000005
      4 #define oo 1e18
      5 struct ji{
      6     int nex,to;
      7 }edge[N];
      8 vector<pair<int,int> >v[N];
      9 int V,E,las,t,n,m,q,l,r,la[N],len[N],nex[N],ch[N][31],f[N][21],head[N],vis[N],val[N];
     10 long long ans,dp[N];
     11 char s[N];
     12 void add(int c){
     13     int p=las,np=las=++V;
     14     len[V]=len[p]+1;
     15     while ((p)&&(!ch[p][c])){
     16         ch[p][c]=las;
     17         p=nex[p];
     18     }
     19     if (!p)nex[las]=1;
     20     else{
     21         int q=ch[p][c],nq=++V;
     22         memcpy(ch[nq],ch[q],sizeof(ch[q]));
     23         nex[nq]=nex[q];
     24         len[nq]=len[p]+1;
     25         ch[p][c]=nex[q]=nex[las]=nq;
     26         while ((p)&&(ch[p][c]==q)){
     27             ch[p][c]=nq;
     28             p=nex[p];
     29         }
     30     }
     31 }
     32 int query(int k,int l){
     33     for(int i=20;i>=0;i--)
     34         if (len[f[k][i]]>=l)k=f[k][i];
     35     return k;
     36 }
     37 void add(int x,int y){
     38     edge[E].nex=head[x];
     39     edge[E].to=y;
     40     head[x]=E++;
     41 }
     42 long long dfs(int k){
     43     if (vis[k])return oo;
     44     if (dp[k]>=0)return dp[k];
     45     vis[k]=1;
     46     long long ans=0;
     47     for(int i=head[k];i!=-1;i=edge[i].nex)ans=max(ans,dfs(edge[i].to));
     48     dp[k]=ans+val[k];
     49     vis[k]=0;
     50     return dp[k];
     51 }
     52 int main(){
     53     scanf("%d",&t);
     54     while (t--){
     55         scanf("%s",s);
     56         int l=strlen(s);
     57         las=V=1;
     58         E=ans=0; 
     59         memset(head,-1,sizeof(head));
     60         memset(vis,0,sizeof(vis));
     61         memset(ch,0,sizeof(ch));
     62         memset(val,0,sizeof(val));
     63         memset(dp,-1,sizeof(dp));
     64         for(int i=l-1;i>=0;i--){
     65             add(s[i]-'a');
     66             la[i]=las;
     67         }
     68         for(int i=1;i<=V;i++)f[i][0]=nex[i];
     69         for(int i=1;i<=20;i++)
     70             for(int j=1;j<=V;j++)f[j][i]=f[f[j][i-1]][i-1];
     71         for(int i=1;i<=V;i++){
     72             v[i].clear();
     73             v[i].push_back(make_pair(len[nex[i]],-nex[i]));
     74             v[i].push_back(make_pair(len[i],-i));
     75         }
     76         int VV=V;
     77         scanf("%d",&n);
     78         for(int i=1;i<=n;i++){
     79             scanf("%d%d",&l,&r);
     80             int k=query(la[l-1],r-l+1);
     81             val[++V]=r-l+1;
     82             v[k].push_back(make_pair(r-l+1,-V));
     83         }
     84         scanf("%d",&m);
     85         for(int i=1;i<=m;i++){
     86             scanf("%d%d",&l,&r);
     87             int k=query(la[l-1],r-l+1);
     88             v[k].push_back(make_pair(r-l+1,-(++V)));
     89         }
     90         for(int i=1;i<=V-n-m;i++){
     91             sort(v[i].begin(),v[i].end());
     92             for(int j=0;j<v[i].size();j++){
     93                 if (val[-v[i][j].second]){
     94                     add(++V,-v[i][j].second);
     95                     v[i][j].second=-V;
     96                 }
     97                 if (j)add(-v[i][j-1].second,-v[i][j].second);
     98             }
     99         }
    100         scanf("%d",&q);
    101         for(int i=1;i<=q;i++){
    102             scanf("%d%d",&l,&r);
    103             add(VV+l,VV+n+r);
    104         }
    105         for(int i=VV+n+m+1;i<=V;i++)ans=max(ans,dfs(i));
    106         if (ans>=oo)ans=-1;
    107         printf("%lld
    ",ans);
    108     }
    109 }
    View Code
  • 相关阅读:
    Codefoces Gym 101652 【最大连续和】
    HYSBZ 4034 【树链剖分】+【线段树 】
    Codeforces Gym 101291C【优先队列】
    Codeforces gym 101291 M (最长交替子序列)【DP】
    HDU 3308 LCIS (经典区间合并)【线段树】
    POJ 3237 Tree (树链剖分+边权转点权)
    POJ 2763 Housewife Wind (树链剖分+边权转点权)
    P1054 等价表达式
    P1107 [BJWC2008]雷涛的小猫
    P1552 [APIO2012]派遣
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/12854552.html
Copyright © 2020-2023  润新知