今天起得比较晚,又浪费了点时间,真可耻。。
下午又为校赛出了俩题,至此,校赛的四道题目已经完毕。又检查了一番,没有错误,就等待着明天的汇总了~。
AC自动机的题目今天就刷了三道,还是没有完成之前的目标。现在vj也进不去了,想通宵,都不给机会~~
只能等明天再刷完了,拖延不是一个好习惯。
----------------------------------------------------------------------------------------------------------
1,hdu-4511-小明系列故事――女友的考验
抢了CZ的FB,心里很高兴,哈哈
AC自动机越来越模板了,就先创建非法路径的自动机。然后再树上求1点到n点的最短路。我当时没有注意要“只能走到比当前所在点编号大的位置; ”的条件,错了N次,伤心。。
#include<stdio.h> #include<algorithm> #include<iostream> #include<stdlib.h> #include<vector> #include<queue> #include<string.h> #include<math.h> using namespace std; #define LL __int64 #define maxn 55 const int maxnode=110*5; const int childnum=55; const int mod=1000000007; const int INF=99999999; struct list { double x; double y; }node[maxn]; struct listt { int p; int t; double dis; friend bool operator <(const listt &a,const listt &b) { return a.dis>b.dis; } }pp,qq; double dist(int x,int y) { double xx,yy; xx=node[x].x-node[y].x; yy=node[x].y-node[y].y; double sum=xx*xx+yy*yy; return 1.0*sqrt(1.0*sum); } priority_queue<listt>que; struct ac_tree { int chd[maxnode][childnum]; int val[maxnode]; int fail[maxnode]; int key[1<<11]; int Q[maxnode]; int ID[128]; int sz; int vis[maxn][maxnode]; void init() { fail[0]=0; for(int i=0;i<childnum;i++) { ID[i]=i; } } void reset() { memset(chd,0,sizeof(chd)); sz=1; } void insert(vector<int>vec,int k) { int p=0; int len=vec.size(); for(int i=0;i<len;i++) { int c=ID[vec[i]]; if(!chd[p][c]) { memset(chd[sz],0,sizeof(chd[sz])); val[sz]=0; chd[p][c]=sz++; } p=chd[p][c]; } val[p]=k; } void ac_build() { int *s=Q,*e=Q; for(int i=1;i<childnum;i++) { if(chd[0][i]) { fail[chd[0][i]]=0; *e++=chd[0][i]; } } while(s!=e) { int u=*s++; if(val[fail[u]])val[u]+=val[fail[u]]; for(int i=1;i<childnum;i++) { int &v=chd[u][i]; if(v) { *e++=v; fail[v]=chd[fail[u]][i]; // val[v]=(val[v]+val[fail[v]]); } else v=chd[fail[u]][i]; } } } int word(int n) { while(!que.empty())que.pop(); memset(vis,0,sizeof(vis)); pp.p=1; pp.t=chd[0][1]; pp.dis=0.0; que.push(pp); int cr; vis[1][pp.t]=1; while(!que.empty()) { pp=que.top(); que.pop(); // cout<<"____________"<<endl; // cout<<pp.p<<endl; if(pp.p==n) { printf("%.2f\n",pp.dis); return 0; } for(int i=pp.p+1;i<=n;i++) { cr=chd[pp.t][i]; if(i==pp.p)continue; if(val[cr])continue; //if(vis[i][cr])continue; // cout<<pp.p<<" "<<i<<" "<<cr<<endl; vis[i][cr]=1; qq.p=i; qq.t=cr; qq.dis=1.0*pp.dis+1.0*dist(pp.p,qq.p); que.push(qq); } } cout<<"Can not be reached!"<<endl; } }AC; char temp[155]; int main() { AC.init(); int n,m,k,x; int T; while(~scanf("%d%d",&n,&m)) { if(!(n||m))break; for(int i=1;i<=n;i++) { scanf("%lf%lf",&node[i].x,&node[i].y); } AC.reset(); vector<int>vec; for(int i=1;i<=m;i++) { vec.clear(); scanf("%d",&k); while(k--) { scanf("%d",&x); vec.push_back(x); } AC.insert(vec,1); } AC.ac_build(); AC.word(n); } return 0; }
1.对自动机上每个状态dp,dp[a][b][c][d]表示经过了a个字符,匹配了b个R,在c这个状态,d是4进制数,表示是否经过串1和串2
也就是一个树上DP,想好状态转移方程就好了。
#include<stdio.h> #include<algorithm> #include<iostream> #include<stdlib.h> #include<string.h> using namespace std; #define LL int const int maxnode=101*2; const int childnum=2; const int mod=1000000007; const int INF=99999999; struct ac_tree { int chd[maxnode][childnum]; int val[maxnode]; int fail[maxnode]; int key[1<<11]; int Q[maxnode]; int ID[128]; int sz; int dp[104][104][maxnode][4]; void init() { fail[0]=0; for(int i=0;i<childnum;i++) { ID[i+‘a‘]=i; } ID[‘R‘]=0;ID[‘D‘]=1; } void reset() { memset(chd,0,sizeof(chd)); sz=1; } void insert(char str[],int k) { int p=0; int len=strlen(str); for(int i=0;i<len;i++) { int c=ID[str[i]]; if(!chd[p][c]) { memset(chd[sz],0,sizeof(chd[sz])); val[sz]=0; chd[p][c]=sz++; } p=chd[p][c]; } val[p]=k; } void ac_build() { int *s=Q,*e=Q; for(int i=0;i<childnum;i++) { if(chd[0][i]) { fail[chd[0][i]]=0; *e++=chd[0][i]; } } while(s!=e) { int u=*s++; // if(val[fail[u]])val[u]|=val[fail[u]]; for(int i=0;i<childnum;i++) { int &v=chd[u][i]; if(v) { *e++=v; fail[v]=chd[fail[u]][i]; val[v]=(val[v]|val[fail[v]]); } else v=chd[fail[u]][i]; } } } int word(int n,int m) { memset(dp,0,sizeof(dp)); dp[0][0][0][0]=1; int cr; int t; for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) { for(int k=0;k<sz;k++) { for(int z=0;z<4;z++) { if(dp[i][j][k][z]==0)continue; // dp[i][j][k][z]%=mod; // cout<<i<<" "<<j<<" "<<k<<" "<<z<<endl; cr=chd[k][0]; t=z|val[cr]; dp[i+1][j][cr][t]+=dp[i][j][k][z]; dp[i+1][j][cr][t]%=mod; cr=chd[k][1]; t=z|val[cr]; dp[i][j+1][cr][t]+=dp[i][j][k][z]; dp[i][j+1][cr][t]%=mod; } } } } int ans=0; for(int i=0;i<sz;i++) { ans+=dp[n][m][i][3]; ans%=mod; } ans=ans%mod; cout<<ans<<endl; } }AC; char temp[155]; int main() { AC.init(); int n,m,k; int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); AC.reset(); for(int i=1;i<=2;i++) { scanf("%s",temp); AC.insert(temp,(1<<(i-1))); } AC.ac_build(); AC.word(n,m); } return 0; }
dp[i][j][k],表示长度为i的串,位于Trie上的状态j,模式串的状态为k的最大价值。
状态压缩一下,就变成了普通的树上DP了,还需要滚动数组压缩一下空间。
#include<stdio.h> #include<algorithm> #include<iostream> #include<stdlib.h> #include<string.h> using namespace std; const int maxnode=101*10; const int childnum=4; const int mod=20090717; const int INF=99999999; struct ac_tree { int chd[maxnode][childnum]; int val[maxnode]; int fail[maxnode]; int key[1<<11]; int Q[maxnode]; int ID[128]; int sz; int dp[2][maxnode][1<<10]; void init() { fail[0]=0; for(int i=0;i<childnum;i++) { ID[i+‘a‘]=i; } ID[‘A‘]=0;ID[‘T‘]=1; ID[‘G‘]=2;ID[‘C‘]=3; } void reset() { memset(chd,0,sizeof(chd)); sz=1; } void insert(char str[],int k,int d) { key[k]=d; int p=0; int len=strlen(str); for(int i=0;i<len;i++) { int c=ID[str[i]]; if(!chd[p][c]) { memset(chd[sz],0,sizeof(chd[sz])); val[sz]=0; chd[p][c]=sz++; } p=chd[p][c]; } val[p]=k; } void ac_build() { int *s=Q,*e=Q; for(int i=0;i<childnum;i++) { if(chd[0][i]) { fail[chd[0][i]]=0; *e++=chd[0][i]; } } while(s!=e) { int u=*s++; // if(val[fail[u]])val[u]|=val[fail[u]]; for(int i=0;i<childnum;i++) { int &v=chd[u][i]; if(v) { *e++=v; fail[v]=chd[fail[u]][i]; val[v]=(val[v]|val[fail[v]]); } else v=chd[fail[u]][i]; } } } int word(int n,int m) { int s=0; int l=1; int tai=(1<<m); int cr,tr; memset(dp,0,sizeof(dp)); dp[0][0][0]=1; for(int i=0;i<n;i++) { l=1-s; memset(dp[l],0,sizeof(dp[l])); // cout<<"__"<<endl; for(int j=0;j<sz;j++) { for(int k=0;k<tai;k++) { if(dp[s][j][k]==0)continue; //cout<<j<<" "<<k<<endl; for(int z=0;z<childnum;z++) { cr=chd[j][z]; // cout<<j<<"+"<<z<<"="<<cr<<endl; tr=val[cr]|k; dp[l][cr][tr]=1; } } } s=l; } int maxx=-1; int tt=0; for(int j=0;j<sz;j++) { for(int k=0;k<tai;k++) { if(dp[s][j][k]==0)continue; // cout<<j<<" "<<k<<endl; tt=0; for(int i=0;i<m;i++) { if(k&(1<<i))tt+=key[1<<i]; } maxx=max(tt,maxx); } } if(maxx<0)cout<<"No Rabbit after 2012!"<<endl; else cout<<maxx<<endl; } }AC; char temp[155]; int main() { AC.init(); int n,m,k; while(~scanf("%d%d",&n,&m)) { AC.reset(); for(int i=1;i<=n;i++) { scanf("%s %d",temp,&k); AC.insert(temp,(1<<(i-1)),k); } AC.ac_build(); AC.word(m,n); } return 0; }
uva 10253 - Series-Parallel Networks,布布扣,bubuko.com
uva 10253 - Series-Parallel Networks
原文:http://blog.csdn.net/keshuai19940722/article/details/26178279