本题是绝对实力不够只能放着的一道题了,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 ; }