http://acm.hdu.edu.cn/showproblem.php?pid=2471
一道BFS的题 而不是自动机,算了不吐槽了...刘汝佳居然放在紫书的自动机章节第一题...Orz
题意就是给你了自动机两枚,判断他两是否是一样的。
判断方法:
1.剪掉死循环
保留可以到达AC态的状态和边。
我们知道自动机会有个AC态,那么对于到达不了AC态的死循环,我们可以把那些状态和那些边(转移函数)减掉。
判断一些状态和一些边(转移函数)能否到达AC态,只要从AC态开始,沿着反向边BFS全部节点。
这里我用了一个Cut函数进行预处理
2.检查两个自动机的每个状态
两个小叽叽,每个有n个状态,两两组合起来就有n*n个状态,n<=2000,所以n^2的复杂度还是可以接受的。
接下来从(0,0)开始BFS,判断可达的每个状态是否都一致,就看两个小叽叽是不是同为AC态或者中间态,还有看是否有一样的边(转移函数)出去。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int MaxN=2011, MaxM=27; #define mp make_pair<int,int> #define pii pair<int,int> bool vis[MaxN][MaxN]; int t,n1,n2; struct Node{ int next[MaxM]; int ac; }dfa1[MaxN], dfa2[MaxN]; bool can[MaxN]; int cas=1,f[MaxN][MaxM],head[MaxN],nex[MaxN*MaxM],cnt,v[MaxN*MaxM]; void Cut(Node *dfa,int *n){ queue<int>q; cnt=0; memset(can,0,sizeof can); memset(head,-1,sizeof head); for(int i=0;i<*n;i++){ if(dfa[i].ac)q.push(i),can[i]=1; for(int j=0;j<t;j++){ if(dfa[i].next[j]==-1)continue; nex[cnt]=head[dfa[i].next[j]]; v[cnt]=i; head[dfa[i].next[j]]=cnt++; } } while(!q.empty()){ int i; for(i=head[q.front()],q.pop(); i!=-1;i=nex[i]){ if(!can[v[i]]){ can[v[i]]=1; q.push(v[i]); } } } for(int i=0;i<*n;i++) for(int j=0;j<t;j++){ if(dfa[i].next[j]!=-1 && !can[dfa[i].next[j]]) dfa[i].next[j]=-1; } } void ReadData(Node *dfa,int *n){ scanf("%d",n); for(int i=0;i<*n;i++){ scanf("%d",&dfa[i].ac); for(int j=0;j<t;j++) scanf("%d",&dfa[i].next[j]); } Cut(dfa,n); } bool BFS(){ queue<pii>q; memset(vis,0,sizeof vis); q.push(mp(0,0)); vis[0][0]=1; while(!q.empty()){ pii cur=q.front();q.pop(); if(dfa1[cur.first].ac != dfa2[cur.second].ac) return false; for(int i=0;i<t;i++){ int nex1=dfa1[cur.first].next[i],nex2=dfa2[cur.second].next[i]; if(!!(nex1+1) != !!(nex2+1))return false; if(nex1==-1)continue; if(!vis[nex1][nex2]){ vis[nex1][nex2]=1; q.push(mp(nex1,nex2)); } } } return true; } int main() { // freopen("data.in","r",stdin); while(scanf("%d", &t)!=EOF && t){ ReadData(dfa1,&n1); ReadData(dfa2,&n2); printf("Case #%d: %s\n",cas++,BFS()?"Yes":"No"); } return 0; }