[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\n",ans);
108     }
109 }
View Code

 

posted @ 2020-05-09 07:08  PYWBKTDA  阅读(145)  评论(0编辑  收藏  举报