分析
未知定长串中不同已知模板串的出现次数问题,一般做法是AC自动机上dp。
考虑背包,\(dp(i,j,k)\)表示当前串长为\(i\),在AC自动机上对应节点\(j\),已匹配的模板串的状态为\(k\)的情况是否出现。用刷表法向后转移。先枚举不定串长度,再枚举AC自动机上节点,然后枚举已知状态,最后枚举字母边转移。
时间复杂度\(O(l \cdot MaxNode \cdot 2^n \cdot SigmaSize)\)。第一维可以滚动,空间复杂度\(O(MaxNode \cdot 2^n)\)
代码
#include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<ctime> #include<iostream> #include<string> #include<vector> #include<list> #include<deque> #include<stack> #include<queue> #include<map> #include<set> #include<algorithm> #include<complex> #pragma GCC optimize ("O0") using namespace std; template<class T> inline T read(T&x){ T data=0; int w=1; char ch=getchar(); while(!isdigit(ch)) { if(ch==‘-‘) w=-1; ch=getchar(); } while(isdigit(ch)) data=10*data+ch-‘0‘,ch=getchar(); return x=data*w; } typedef long long ll; const int INF=0x7fffffff; const int MAXN=1010; const int SigmaSize=4; bool dp[2][MAXN][1100]; int mp[15]; struct Trie { int next[MAXN][SigmaSize]; int fail[MAXN]; int end[MAXN]; int root,ncnt; int newnode() { for(int i=0;i<SigmaSize;++i) next[ncnt][i]=-1; end[ncnt++]=0; return ncnt-1; } void init() { ncnt=0; root=newnode(); } int id(char c) { if(c==‘A‘) return 0; else if(c==‘G‘) return 1; else if(c==‘T‘) return 2; else return 3; } void insert(char*str,int v) { int Now=root; int len=strlen(str); for(int i=0;i<len;++i) { int c=id(str[i]); if(next[Now][c]==-1) next[Now][c]=newnode(); Now=next[Now][c]; } end[Now]|=(1<<v); } void getfail() { queue<int>Q; fail[root]=root; for(int i=0;i<SigmaSize;++i) { if(next[root][i]==-1) next[root][i]=root; else { fail[next[root][i]]=root; Q.push(next[root][i]); } } while(!Q.empty()) { int Now=Q.front(); Q.pop(); end[Now]|=end[fail[Now]]; for(int i=0;i<SigmaSize;++i) { if(next[Now][i]==-1) next[Now][i]=next[fail[Now]][i]; else { fail[next[Now][i]]=next[fail[Now]][i]; Q.push(next[Now][i]); } } } } void solve(int n,int l) { memset(dp,sizeof(dp)); dp[0][0][0]=1; // dp[len][node][state] int cur=1; for(int i=1;i<=l;++i) { memset(dp[cur],sizeof(cur)); for(int j=0;j<ncnt;++j) { for(int k=0;k<(1<<n);++k) { for(int q=0;q<SigmaSize;++q) { int nxt=next[j][q]; dp[cur][nxt][k|end[nxt]]=(dp[cur][nxt][k|end[nxt]]||dp[cur^1][j][k]); } } } cur^=1; } int ans=-INF; for(int i=0;i<ncnt;++i) for(int j=0;j<(1<<n);++j) { if(dp[cur^1][i][j]) { int sum=0; for(int k=0;k<n;++k) if(j&(1<<k)) sum+=mp[k]; ans=max(ans,sum); } } if(ans<0) printf("No Rabbit after 2012!\n"); else printf("%d\n",ans); } }AC; char s[110]; int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); int n,l,w; while(~scanf("%d %d",&n,&l)) { AC.init(); for(int i=0;i<n;++i) { scanf("%s %d",s,&w); AC.insert(s,i); mp[i]=w; } AC.getfail(); AC.solve(n,l); } // fclose(stdin); // fclose(stdout); return 0; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。