UVALive 6674 Dictionary AC自动机+最小树形图+输出最小树形图

本题是绝对实力不够只能放着的一道题了,AC自动机以及最小树形图已经求出,但是如何输出却迟迟无法想到。

唉。。果然太弱,显放着,等以后有空了再思考一下吧= =||


代码如下:


#include <iostream>  
#include <queue>  
#include <stack>  
#include <map>  
#include <set>  
#include <bitset>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
#include <climits>  
#include <cstdlib>
#include <math.h>
#define maxn 50
#define eps 1e-10
#define mod 1000000009
#define INF 0x3f3f3f3f
#define lowbit(x) (x&(-x))  
//#define lson o<<1, L, mid  
//#define rson o<<1 | 1, mid+1, R  
typedef long long LL;
//typedef int LL;
using namespace std;
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REPV( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define clear( a , x ) memset ( a , x , sizeof a )

const int MAXW = 26 ;
const int MAXN = 505 ;
const int MAXQ = 1000000 ;
const int MAXE = 1000000 ;

struct Line {
	int u , v , c , f , word ;
	int now , pre ;
} ;

struct Edge {
	int v , word , f , n ;
} ;

struct Trie {
	int end[MAXN] ;
	int next[MAXN][MAXW] ;
	int fail[MAXN] ;
	int Q[MAXQ] , head , tail ;
	int P , root ;
	int n ;
	char buf[MAXN] ;
	int word[MAXN] ;
	int NV , NE ;
	
	//----------------------------
	Line E[MAXE] ;
	Edge edge[MAXE] ;
	int H[MAXN] , cntE ;
	int In[MAXN] ;
	int pre[MAXN] ;
	int vis[MAXN] ;
	int idx[MAXN] ;
	int ans[MAXN] ;
	int num[MAXN] ;
	bool mark[MAXN][MAXN] ;
	int p[MAXN] ;
	int cnt ;
	
	int newnode ( int x ) {
		REP ( i , MAXW )
			next[P][i] = -1 ;
		end[P] = P ;
		word[P] = x ;
		return P ++ ;
	}
	
	void init () {
		NE = 0 ;
		P = 0 ;
		cnt = 0 ;
		cntE = 0 ;
		clear ( H , -1 ) ;
		clear ( num , 0 ) ;
		clear ( mark , 0 ) ;
		root = newnode ( -'a' + 'O' ) ;
	}
	
	int get ( char &a ) {
		return a - 'a' ;
	}
	
	void insert ( char buf[] ) {
		int now = root ;
		for ( int i = 0 ; buf[i] ; ++ i ) {
			int x = get ( buf[i] ) ;
			if ( next[now][x] == -1 )
				next[now][x] = newnode ( x ) ;
			now = next[now][x] ;
		}
	}
	
	void addedge ( int u , int v , int c , int word ) {
		E[NE].u = E[NE].pre = u ;
		E[NE].v = E[NE].now = v ;
		E[NE].c = E[NE].f = c ;
		E[NE].word = word ;
		NE ++ ;
	}
	
	void build () {
		head = tail = 0 ;
		REP ( i , MAXW ) {
			if ( next[root][i] == -1 )
				next[root][i] = root ;
			else {
				Q[tail ++] = next[root][i] ;
				addedge ( root , next[root][i] , 1 , word[next[root][i]] ) ;
				fail[next[root][i]] = root ;
			}
		}
		while ( head != tail ) {
			int now = Q[head ++] ;
			REP ( i , MAXW ) {
				if ( next[now][i] == -1 ) {
					next[now][i] = next[fail[now]][i] ;
				}
				else {
					fail[next[now][i]] = next[fail[now]][i] ;
					addedge ( now , next[now][i] , 1 , word[next[now][i]] ) ;
					Q[tail ++] = next[now][i] ;
				}
			}
		}
		REP ( i , P )
			if ( fail[i] != root )
				addedge ( i , fail[i] , 0 , word[fail[i]] ) ;
	}
	
	int zhuliu () {
		int res = 0 ;
		NV = P ;
		while ( 1 ) {
			clear ( In , INF ) ;
			REP ( i , NE ) {
				int u = E[i].u ;
				int v = E[i].v ;
				if ( u != v && In[v] > E[i].c ) {
					In[v] = E[i].c ;
					pre[v] = u ;
					ans[E[i].now] = i ;
				}
			}
			int cnt = 1 ;
			clear ( idx , -1 ) ;
			clear ( vis , 0 ) ;
			pre[0] = 0 ;
			idx[0] = 0 ;
			In[0] = 0 ;
			REP ( i , NV ) {
				res += In[i] ;
				int v = i ;
				while ( vis[v] != i && idx[v] == -1 && v != 0 ) {
					vis[v] = i ;
					v = pre[v] ;
				}
				if ( idx[v] == -1 && v != 0 ) {
					for ( int u = pre[v] ; u != v ; u = pre[u] )
						idx[u] = cnt ;
					idx[v] = cnt ++ ;
				}
			}
			if ( cnt == 1 )
				break ;
			REP ( i , NV )
				if ( idx[i] == -1 )
						idx[i] = cnt ++ ;
			REP ( i , NE ) {
				int u = E[i].u ;
				int v = E[i].v ;
				E[i].u = idx[u] ;
				E[i].v = idx[v] ;
				if ( idx[u] != idx[v] )
					E[i].c -= In[v] ;
			}
			NV = cnt ;
		}
		return res ;
	}
	
	void add ( int u , int v , int word , int f ) {
		edge[cntE].v = v ;
		edge[cntE].f = f ;
		edge[cntE].word = word ;
		edge[cntE].n = H[u] ;
		H[u] = cntE ++ ;
	}
	
	void dfs ( int u ) {
		for ( int i = H[u] ; ~i ; i = edge[i].n ) {
			int v = edge[i].v ;
			num[v] = ++ cnt ;
			printf ( "%d -> %d %c\n" , num[u] , num[v] , edge[i].word + 'a' ) ;
			dfs ( v ) ;
		}
	}
	
	int find ( int x ) {
		return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ;
	}
	
	void solve () {
		init () ;
		REP ( i , n ) {
			scanf ( "%s" , buf ) ;
			insert ( buf ) ;
		}
		build () ;
		int res = zhuliu () + 1 ;
		printf ( "%d\n0\n" , res ) ;
		REPF ( i , 0 , P - 1 )
			p[i] = i ;
		REPF ( i , 1 , P - 1 )
			if ( !E[ans[i]].f ) {
				printf ( "-------%d -> %d\n" , E[ans[i]].now , E[ans[i]].pre ) ;
				p[E[ans[i]].now] = E[ans[i]].pre ;
			}
		REPF ( i , 1 , P - 1 )
			find ( i ) ;
		REPF ( i , 1 , P - 1 )
			printf ( "%d -> %d\n" , p[E[ans[i]].pre] , p[E[ans[i]].now] ) ;
		
		REPF ( i , 1 , P - 1 )
			if ( p[E[ans[i]].pre] != p[E[ans[i]].now] && !mark[p[E[ans[i]].pre]][p[E[ans[i]].now]] ) {
				mark[p[E[ans[i]].pre]][p[E[ans[i]].now]] = 1 ;
				add ( p[E[ans[i]].pre] , p[E[ans[i]].now] , E[ans[i]].word , E[ans[i]].f ) ;
			}
		num[0] = ++ cnt ;
		dfs ( 0 ) ;
	}
} ;

Trie c ;

int main () {
	while ( ~scanf ( "%d" , &c.n ) )
		c.solve () ;
	return 0 ;
}


你可能感兴趣的:(UVALive 6674 Dictionary AC自动机+最小树形图+输出最小树形图)