CF1163D Mysterious Code(AC自動機+dp)
阿新 • • 發佈:2020-08-01
本題觀察資料量非常小,並且求的是多串匹配,因此可以考慮使用ac自動機
設計dp狀態為f[][],表示c中前i個字元匹配到第j個節點所能達到的最大值。
首先我們知道,兩個匹配串在結束位置的點分別是+-1,而所有字首能包含這兩個字串的,也應該設為對應的數值,對fail樹進行修改進行。
dp的時候,列舉位置,列舉之前處於的節點位置,當前位置是什麼字元,進行dp即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+10; struct node{ int cnt; nodeView Code* nxt[27]; node * fail; vector<node *> num; }*rt; node pool[N]; int n,idx; int val[N]; int num; int f[1100][200]; void insert(string s,int x){ node *p=rt; int i; for(i=0;i<s.size();i++){ int sign=s[i]-'a'; if(p->nxt[sign]==NULL){ p->nxt[sign]=pool+(++idx); p->nxt[sign]->cnt=++num; } p=p->nxt[sign]; if(i==(int)s.size()-1){ val[p->cnt]=x; } } } void build(){ int i; queue<node *> q; rt->fail=rt; for(i=0;i<26;i++){ if(rt->nxt[i]){ rt->nxt[i]->fail=rt; rt->num.push_back(rt->nxt[i]); q.push(rt->nxt[i]); } else{ rt->nxt[i]=rt; rt->nxt[i]->fail=rt; } } while(q.size()){ auto t=q.front(); q.pop(); for(i=0;i<26;i++){ if(t->nxt[i]){ t->nxt[i]->fail=t->fail->nxt[i]; t->fail->nxt[i]->num.push_back(t->nxt[i]); q.push(t->nxt[i]); } else{ t->nxt[i]=t->fail->nxt[i]; } } val[t->cnt]+=val[t->fail->cnt]; } } int main(){ ios::sync_with_stdio(false); int i; rt=pool; rt->cnt=0; string c; cin>>c; n=c.size(); c=" "+c; string s,t; cin>>s>>t; insert(s,1); insert(t,-1); build(); memset(f,-0x3f,sizeof f); f[0][0]=0; for(i=1;i<=n;i++){ for(int j=0;j<=num;j++){ for(int k=0;k<26;k++){ if(c[i]=='*'||(c[i]=='a'+k)){ int id=(pool+j)->nxt[k]->cnt; f[i][id]=max(f[i][id],f[i-1][j]+val[id]); } } } } int ans=-0x3f3f3f3f; for(i=0;i<=num;i++) ans=max(ans,f[n][i]); cout<<ans<<endl; }