zoukankan      html  css  js  c++  java
  • 第九周 10.25-10.31

    10.25

    HDU 4117 GRE Words

    卡了很久的一个题目。比较综合。

    看了很久题解还是各种写挫。

    毕竟除了模拟题都没敲过那么长的。

    题意:按顺序给N个单词,每个单词有权值,删去其中任意单词,使得前面的单词为后面单词的子串,求最大权值和。

    做法:先建好AC自动机。

       最先想到的方法应该是这样的。

       定义dp[i]为以第i个串为最后一个串的答案。

       转移是dp[i]=max{W[i],dp[j]+W[i]}(j为i子串)

       那么只要再拿这N个单词在AC自动机上匹配一遍。

       每过一个节点相当于经过这个串的一个前缀。而这个节点的fail指向的是这个前缀的后缀。

       于是经过的每个节点时都通过fail一直走到root就遍历了这个串的所有子串。

       那么我们不妨定义f[u]为节点u所对应的单词的所有后缀的答案。

       那么可以用这种方法借助f[]来求出dp。

       

       然而这样是T的。

       于是考虑一种用线段树优化的方法。

       

       考虑到我们每次是顺着fail指针更新答案的。而且每次更新一个节点后只会影响fail指向它的节点。

       按照fail反向建树。这样每个父节点都是孩子节点的前缀。也就是每次更新一个节点后只影响它的子树。

       先在fail树上dfs一遍打好时间戳。

       线段树的每个节点维护时间戳所对应的fail树上节点的f[]值。

       于是按照段更新的区间最值线段树写就可以了。

       每次询问所有前缀的f[]。再更新末节点对应子树的f[]。

       所有取最大即为答案。

       

       最后防爆栈黑科技交C++。   

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <queue>
      7 using namespace std;
      8 const int maxnode=3e5+10,sigma_size=26;
      9 const int maxn=2e4+10;
     10 int n,p[maxn],W[maxn];
     11 char s[maxnode];
     12 
     13 //fail_tree
     14 int cnt,headlist[maxnode];
     15 int timer,dfn[maxnode][2];
     16 struct e
     17 {
     18     int to,pre;
     19 } edge[2*maxnode];
     20 
     21 void add(int from,int to)
     22 {
     23     cnt++;
     24     edge[cnt].pre=headlist[from];
     25     edge[cnt].to=to;
     26     headlist[from]=cnt;
     27 }
     28 
     29 void dfs(int pos,int fa)
     30 {
     31     dfn[pos][0]=++timer;
     32     for(int i=headlist[pos];i;i=edge[i].pre)
     33     {
     34         int to=edge[i].to;
     35         if(to==fa) continue;
     36         dfs(to,pos);
     37     }
     38     dfn[pos][1]=++timer;
     39 }
     40 
     41 //seg_tree
     42 struct seg_tree
     43 {
     44     int l,r,val;
     45 }tree[maxnode<<3];
     46 
     47 void buildtree(int pos,int l,int r)
     48 {
     49     tree[pos].l=l;
     50     tree[pos].r=r;
     51     tree[pos].val=0;
     52     if(l<r)
     53     {
     54         buildtree(pos*2,l,(l+r)/2);
     55         buildtree(pos*2+1,(l+r)/2+1,r);
     56     }
     57 }
     58 
     59 void pushdown(int pos)
     60 {
     61     tree[2*pos].val=max(tree[2*pos].val,tree[pos].val);
     62     tree[2*pos+1].val=max(tree[2*pos+1].val,tree[pos].val);
     63 }
     64 
     65 void update(int pos,int l,int r,int val)
     66 {
     67     if(tree[pos].l>=l&&tree[pos].r<=r) tree[pos].val=max(tree[pos].val,val);
     68     else
     69     {
     70         pushdown(pos);
     71         if((tree[pos].l+tree[pos].r)/2>=r) update(pos*2,l,r,val);
     72         else if((tree[pos].l+tree[pos].r)/2<l) update(pos*2+1,l,r,val);
     73         else
     74         {
     75             update(pos*2,l,r,val);
     76             update(pos*2+1,l,r,val);
     77         }
     78     }
     79 }
     80 
     81 int query(int pos,int l,int r)
     82 {
     83     if(tree[pos].l>=l&&tree[pos].r<=r) return tree[pos].val;
     84     int ret=0;
     85     pushdown(pos);
     86     if((tree[pos].l+tree[pos].r)/2>=r) ret=max(ret,query(pos*2,l,r));
     87     else if((tree[pos].l+tree[pos].r)/2<l) ret=max(ret,query(pos*2+1,l,r));
     88     else
     89     {
     90         ret=max(ret,query(pos*2,l,r));
     91         ret=max(ret,query(pos*2+1,l,r));
     92     }
     93     return ret;
     94 }
     95 
     96 struct Ac_auto
     97 {
     98     int Next[maxnode][sigma_size];
     99     int fail[maxnode];
    100     int sz;
    101     Ac_auto(){sz=1;memset(Next[0],0,sizeof(Next[0]));}
    102     void init(){sz=1;memset(Next[0],0,sizeof(Next[0]));}
    103     int idx(char c) {return c-'a';}
    104 
    105     void insert(char *s)
    106     {
    107         int u=0,n=strlen(s);
    108         for(int i=0;i<n;i++)
    109         {
    110             int c=idx(s[i]);
    111             if(!Next[u][c])
    112             {
    113                 memset(Next[sz],0,sizeof(Next[sz]));
    114                 Next[u][c]=sz++;
    115             }
    116             u=Next[u][c];
    117         }
    118     }
    119 
    120     void build()
    121     {
    122         queue<int> q;
    123         fail[0]=0;
    124         for(int i=0;i<sigma_size;i++) if(Next[0][i])
    125         {
    126             fail[Next[0][i]]=0;
    127             q.push(Next[0][i]);
    128         }
    129         while(!q.empty())
    130         {
    131             int pos=q.front(); q.pop();
    132             for(int i=0;i<sigma_size;i++)
    133             {
    134                 if(!Next[pos][i]) Next[pos][i]=Next[fail[pos]][i];
    135                 else
    136                 {
    137                     fail[Next[pos][i]]=Next[fail[pos]][i];
    138                     q.push(Next[pos][i]);
    139                 }
    140             }
    141         }
    142     }
    143 
    144     void fail_tree()
    145     {
    146         cnt=0;
    147         memset(headlist,0,sizeof(headlist));
    148         for(int i=1;i<sz;i++)
    149         {
    150             add(i,fail[i]);
    151             add(fail[i],i);
    152         }
    153     }
    154 
    155     int solve()
    156     {
    157         int ret=0;
    158         for(int i=1;i<=n;i++)
    159         {
    160             int u=0,tmp=0;
    161             for(int j=p[i-1];j<p[i];j++)
    162             {
    163                 u=Next[u][idx(s[j])];
    164                 tmp=max(tmp,query(1,dfn[u][0],dfn[u][0])+W[i]);
    165             }
    166             ret=max(ret,tmp);
    167             update(1,dfn[u][0],dfn[u][1],tmp);
    168         }
    169         return ret;
    170     }
    171 
    172 }ACA;
    173 
    174 
    175 int main(void)
    176 {
    177     int T; scanf("%d",&T);
    178     for(int kase=1;kase<=T;kase++)
    179     {
    180         scanf("%d",&n);
    181         ACA.init();
    182         for(int i=1;i<=n;i++)
    183         {
    184             scanf("%s%d",s+p[i-1],W+i);
    185             ACA.insert(s+p[i-1]);
    186             p[i]=p[i-1]+strlen(s+p[i-1]);
    187         }
    188         ACA.build();
    189         ACA.fail_tree();
    190         timer=0;
    191         dfs(0,-1);
    192         buildtree(1,1,timer);
    193         printf("Case #%d: %d
    ",kase,ACA.solve());
    194     }
    195     return 0;
    196 }
    Aguin

    10.26-10.31

    什么都没干。

  • 相关阅读:
    CH1301 邻值查找【set应用】
    poj1185 炮兵阵地【状压DP】
    codeforces#516 Div2---ABCD
    2017ACM-ICPC沈阳区域赛
    poj2411 Mondriaan's Dream【状压DP】
    hdu2196 Computer【树形DP】【换根法】
    poj3345 Bribing FIPA【树形DP】【背包】
    poj1463 Strategic game【树形DP】
    poj1191 棋盘分割【区间DP】【记忆化搜索】
    CH5E09 能量相连【区间DP】
  • 原文地址:https://www.cnblogs.com/Aguin/p/4908313.html
Copyright © 2011-2022 走看看