zoukankan      html  css  js  c++  java
  • 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
    ", ++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
    ", ++ca, ts.c_str());
    	}
    	return 0;
    }
    
  • 相关阅读:
    BZOJ 1391: [Ceoi2008]order
    BZOJ 4504: K个串
    2019 年百度之星·程序设计大赛
    POJ 2398 Toy Storage (二分 叉积)
    POJ 2318 TOYS (二分 叉积)
    HDU 6697 Closest Pair of Segments (计算几何 暴力)
    HDU 6695 Welcome Party (贪心)
    HDU 6693 Valentine's Day (概率)
    HDU 6590 Code (判断凸包相交)
    POJ 3805 Separate Points (判断凸包相交)
  • 原文地址:https://www.cnblogs.com/chanme/p/4843489.html
Copyright © 2011-2022 走看看