hdu2471 History of Languages,ACM/ICPC Hangzhou2008 UVa1671

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;
}


你可能感兴趣的:(bfs,自动机)