HDU5487 Difference of Languages(BFS)

题意:给你两个自动机,求出最短的(如果有相同最短的则求出字典序最小的)能被其中一个自动机接收而不能被另外一个自动机接收的字符串。

一看是自动机以为是神题,后来比赛最后才有思路。

两个自动机的状态都是小于1000的,所以可以建一个图,每个结点(u,v)表示当前处于自动机1的状态u和自动机2的状态v,然后相应的这些状态接收[a-z]的字符就会转移到下一个状态。然后从原点(0,0)开始广搜,搜到的第一个accpet[u]!=accept[v]的即是所求的状态。(处理的时候要给每个自动机加一个状态,用来表示失配的时候的情况,这个状态的所有后继都转移向自己,而且本身不是accpet状态,广搜即可)

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
using namespace std;

#define maxn 1005

int n1, m1, k1;
int n2, m2, k2;

bool tar1[maxn];
bool tar2[maxn];

int go1[maxn][26];
int go2[maxn][26];

int prestate[maxn*maxn];
char prechar[maxn*maxn];

bool vis[maxn*maxn];

bool check(int x)
{
	return tar1[x / n2] != tar2[x%n2];
}

int nextState(int x, int c)
{
	return go1[x / n2][c] * n2 + go2[x%n2][c];
}

int main()
{
	int T; cin >> T; int ca = 0;
	while (T--)
	{
		memset(go1, -1, sizeof(go1));
		memset(go2, -1, sizeof(go2));
		memset(tar1, 0, sizeof(tar1));
		memset(tar2, 0, sizeof(tar2));

		int accept;
		int ui, vi;
		char ci[3];

		scanf("%d%d%d", &n1, &m1, &k1);
		for (int i = 0; i < k1; ++i){
			scanf("%d", &accept);
			tar1[accept] = true;
		}
		for (int i = 0; i < m1; ++i){
			scanf("%d%d%s", &ui, &vi, ci);
			go1[ui][ci[0] - 'a'] = vi;
		}
		for (int i = 0; i <= n1; ++i){
			for (int k = 0; k < 26; ++k){
				if (go1[i][k] == -1) go1[i][k] = n1;
			}
		}

		scanf("%d%d%d", &n2, &m2, &k2);
		for (int i = 0; i < k2; ++i){
			scanf("%d", &accept);
			tar2[accept] = true;
		}
		for (int i = 0; i < m2; ++i){
			scanf("%d%d%s", &ui, &vi, ci);
			go2[ui][ci[0] - 'a'] = vi;
		}
		for (int i = 0; i <= n2; ++i){
			for (int k = 0; k < 26; ++k){
				if (go2[i][k] == -1) go2[i][k] = n2;
			}
		}
		++n1; ++n2;

		int ans = -1;
		memset(vis, 0, sizeof(vis));
		queue<int> Q;
		Q.push(0);
		vis[0] = true;
		while (!Q.empty())
		{
			int state = Q.front(); Q.pop();
			if (check(state)){
				ans = state;
				break;
			}
			for (int k = 0; k < 26; ++k){
				int nstate = nextState(state, k);
				if (!vis[nstate]){
					Q.push(nstate);
					vis[nstate] = true;
					prestate[nstate] = state;
					prechar[nstate] = k;
				}
			}
		}
		if (-1 == ans){
			printf("Case #%d: 0\n", ++ca);
			continue;
		}
		string ts;
		while (ans != 0){
			ts.push_back(char('a' + prechar[ans]));
			ans = prestate[ans];
		}
		reverse(ts.begin(), ts.end());
		printf("Case #%d: %s\n", ++ca, ts.c_str());
	}
	return 0;
}

 

posted @ 2015-09-28 10:43  chanme  阅读(212)  评论(0编辑  收藏  举报