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

纵饮孤独 提交于 2019-12-06 03:31:08

题意: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\n",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\n",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 /**************************************************************************************/

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!