• AC自动机fail树上dfs序建线段树+动态memset清空


    题意:http://acm.hdu.edu.cn/showproblem.php?pid=4117

    思路:https://blog.csdn.net/u013306830/article/details/77586562

    主要就是卡你内存,AC自动机的字典树得要用了再清空。

    代码有点长吧。。。

      1 #include <cstdio>//sprintf islower isupper
      2 #include <iostream>//pair
      3 #include <string.h>//strstr substr strcat
      4 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
      5 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
      6 #define mem(a,b) memset(a,b,sizeof(a))
      7 #define pr printf
      8 #define sc scanf
      9 #define ls rt<<1
     10 #define rs rt<<1|1
     11 const int N=3e5+10;
     12 
     13 char s[N];
     14 int pos[20004],val[20004];
     15 //-------------------------------
     16 class mymap
     17 {
     18 public:
     19     int tot;
     20     int head[N];
     21     int SZ[N];
     22     int dfn[N],cnt;
     23     struct
     24     {
     25         int to,next;
     26     }edge[N];
     27     void Init(int n)
     28     {
     29         tot=0;
     30         cnt=-1;
     31         for(int i=0;i<=n;++i)
     32             head[i]=SZ[i]=0;
     33     }
     34     void add(int from,int to)
     35     {
     36         ++tot;
     37         edge[tot].to=to;
     38         edge[tot].next=head[from];
     39         head[from]=tot;
     40     }
     41     int dfs(int u)
     42     {
     43         ++cnt;
     44         dfn[u]=cnt;
     45         SZ[dfn[u]]=1;
     46         for(int i=head[u];i;i=edge[i].next)
     47         {
     48         //    cout<<edge[i].first<<endl;
     49             SZ[dfn[u]]+=dfs(edge[i].to);
     50         }
     51         return SZ[dfn[u]];
     52     }
     53 }TREE;
     54 
     55 class seg_tree
     56 {
     57 public:
     58     int max_[N<<2],add[N<<2];
     59 
     60     void up(int rt)
     61     {
     62         max_[rt]=max(max_[ls],max_[rs]);
     63     }
     64     void dn(int rt)
     65     {
     66         if(add[rt])
     67         {
     68             add[ls]=max(add[ls],add[rt]);
     69             add[rs]=max(add[rs],add[rt]);
     70             max_[ls]=max(max_[ls],add[rt]);
     71             max_[rs]=max(max_[rs],add[rt]);
     72             add[rt]=0;
     73         }
     74     }
     75     void Build(int l,int r,int rt)
     76     {
     77         max_[rt]=0;
     78         add[rt]=0;
     79         if(l==r)
     80         {
     81             return;
     82         }
     83         int mid=(l+r)>>1;
     84 
     85         Build(l,mid,rt<<1);
     86         Build(mid+1,r,rt<<1|1);
     87     }
     88     int Q_dot(int pos,int l,int r,int rt)
     89     {
     90         if(l==r)
     91         {
     92             return max_[rt];
     93         }
     94 
     95         int mid=(l+r)>>1;
     96         dn(rt);
     97         if(pos<=mid)
     98             return Q_dot(pos,l,mid,rt<<1);
     99         else
    100             return Q_dot(pos,mid+1,r,rt<<1|1);
    101     }
    102     void update_qu(int L,int R,int V,int l,int r,int rt)
    103     {
    104         if(L>R)return;
    105         if(L<=l&&r<=R)
    106         {
    107             max_[rt]=max(max_[rt],V);
    108             add[rt]=max(add[rt],V);
    109             return;
    110         }
    111 
    112         int mid=(l+r)>>1;
    113         dn(rt);
    114         if(L<=mid)
    115             update_qu(L,R,V,l,mid,rt<<1);
    116         if(R>mid)
    117             update_qu(L,R,V,mid+1,r,rt<<1|1);
    118         up(rt);
    119     }
    120 }SEG;
    121 
    122 class ac_automaton
    123 {
    124 public:
    125     int tot;
    126     int trie[N][27];
    127     int fail[N];
    128     //other
    129     //--------------
    130     void Insert(int l,int r)
    131     {
    132         int rt=0;
    133         for(int i=l;i<=r;++i)
    134         {
    135             int id=s[i]-'a'+1;
    136             if(!trie[rt][id])
    137             {
    138                 mem(trie[++tot],0);
    139                 trie[rt][id]=tot;
    140             }
    141             rt=trie[rt][id];
    142         }
    143     }
    144     queue<int>q;
    145     void Getfail()
    146     {
    147         for(int i=1;i<=26;++i)
    148         {
    149             int id=trie[0][i];
    150             if(id)
    151             {
    152                 fail[id]=0;
    153                 q.push(id);
    154             }
    155         }
    156         while(!q.empty())
    157         {
    158             int rt=q.front();q.pop();
    159             for(int i=1;i<=26;++i)
    160             {
    161                 int id=trie[rt][i];
    162                 if(id)
    163                 {
    164                     fail[id]=trie[fail[rt]][i];
    165                     q.push(id);
    166                 }
    167                 else
    168                     trie[rt][i]=trie[fail[rt]][i];
    169             }
    170         }
    171     }
    172     int Find(int l,int r,int id,int n)
    173     {
    174         int rt=0;
    175         int pos=0;
    176         int temp_max=0;
    177         for(int i=l;i<=r;++i)
    178         {
    179             rt=trie[rt][s[i]-'a'+1];
    180             pos=TREE.dfn[rt];
    181             int temp_val=SEG.Q_dot(pos,1,n,1)+val[id];
    182             temp_max=max(temp_max,temp_val);
    183         }
    184         SEG.update_qu(pos,pos+TREE.SZ[pos]-1,temp_max,1,n,1);
    185     //    for(int j=1;j<=n;++j)pr("%d ",SEG.Q_dot(j,1,n,1));
    186     //    cout<<endl<<"----------------------------------"<<endl;
    187         return temp_max;
    188     }
    189 }AC;
    190 
    191 void solve()
    192 {
    193     AC.tot=0;
    194     mem(AC.trie[0],0);
    195     int n,tot;
    196     sc("%d",&n);
    197     pos[1]=1;
    198     for(int i=1;i<=n;++i)
    199     {
    200         sc("%s %d",s+pos[i],&val[i]);
    201         int l=strlen(s+pos[i]);
    202         AC.Insert(pos[i],pos[i]+l-1);
    203         pos[i+1]=pos[i]+l;
    204     }
    205     tot=AC.tot;
    206 //    pr("%s
    ",s+1);
    207     AC.Getfail();
    208     TREE.Init(tot);
    209     SEG.Build(1,tot,1);
    210     for(int i=1;i<=AC.tot;++i)
    211         TREE.add(AC.fail[i],i);
    212     TREE.SZ[0]=TREE.dfs(0);
    213     int ans=0;
    214     for(int i=1;i<=n;++i)
    215         ans=max(ans,AC.Find(pos[i],pos[i+1]-1,i,tot));
    216     pr("%d
    ",ans);
    217 }
    218 
    219 int main()
    220 {
    221     int T,cnt=0;
    222     sc("%d",&T);
    223     while(T--)
    224     {
    225         pr("Case #%d: ",++cnt);
    226         solve();
    227     }
    228     return 0;
    229 }
    230 
    231 /**************************************************************************************/
  • 相关阅读:
    crontab与系统时间不一致
    MySQL构造测试数据
    【SQL优化】SQL优化工具
    mysql case when then 使用
    update没带where,寻找问题的思路
    线程池
    线程理论
    数据共享
    进程池
    管道
  • 原文地址:https://www.cnblogs.com/--HPY-7m/p/11960478.html
Copyright © 2020-2023  润新知