zoj 3535 Gao the String II(ac自动机+dp)
时间:2014-04-08 17:51:00
收藏:0
阅读:940
Gao the String II
题意:有字符串集合A,B。每个集合内最多有50个字符串,每个字符串长度不超过10,用A集合内的字符串link(link操作就是连接,比如已经link得到一个s,那么可以直接在s后面接上一个A里面的字符串,也可以将s的后缀跟要接上的串的前缀叠在一起连接)成一个长度不超过L的字符串s,问s与每一个B里面的字符串匹配,得到的匹配位置数之和最大是多少?ps:比赛的时候没注意到时不超过L啊,还以为一定要L,晕死。。。
解题思路:如果我们得到了所有的s,那么跟B去匹配就完事了。但是,很显然,s的可能情况太多。建立B的ac自动机(为什么想到自动机?不知道,反正就是想到了),然后定义dp状态,dp[i][j][k]表示s的长度为i,以A中的第j个字符串为结尾,匹配到自动机上的k节点时,最大的匹配点数是多少。要预处理很多东西,首先要预处理出,A集合里的字符串两两匹配的所有能link的位置,然后还要预处理从自动机的t1节点,接上一个A里面的每一个字符串的每一个后缀能增加多少个匹配点,接上之后,会匹配到那个节点上。这些弄好了,dp递推的复杂度才会合适。
代码:
解题思路:如果我们得到了所有的s,那么跟B去匹配就完事了。但是,很显然,s的可能情况太多。建立B的ac自动机(为什么想到自动机?不知道,反正就是想到了),然后定义dp状态,dp[i][j][k]表示s的长度为i,以A中的第j个字符串为结尾,匹配到自动机上的k节点时,最大的匹配点数是多少。要预处理很多东西,首先要预处理出,A集合里的字符串两两匹配的所有能link的位置,然后还要预处理从自动机的t1节点,接上一个A里面的每一个字符串的每一个后缀能增加多少个匹配点,接上之后,会匹配到那个节点上。这些弄好了,dp递推的复杂度才会合适。
代码:
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> #include<queue> using namespace std ; const int N = 51 ; const int maxn = 501 ; int dp[N][N][maxn] , inc[N][N][N] ; vector<int> vec[N][N] ; short add[12][N][maxn] , to[12][N][maxn] ; char s1[N][N] , s2[N][N] ; int n , m , l ; int len[N] ; struct AC_auto { int c[26][maxn] , tot , cnt[maxn] , fail[maxn] ; queue<int> Q ; int new_node () { int i ; for ( i = 0 ; i < 26 ; i ++ ) c[i][tot] = 0 ; fail[tot] = cnt[tot] = 0 ; return tot ++ ; } void insert ( char *s ) { int now = 0 ; for ( ; *s ; s ++ ) { int k = *s - ‘a‘ ; if ( !c[k][now] ) c[k][now] = new_node () ; now = c[k][now] ; } cnt[now] ++ ; } void get_fail () { int u = 0 , e , i , j ; for ( i = 0 ; i < 26 ; i ++ ) if ( c[i][u] ) Q.push ( c[i][u] ) ; while ( !Q.empty () ) { u = Q.front () ; Q.pop () ; for ( i = 0 ; i < 26 ; i ++ ) { if ( c[i][u] ) { e = c[i][u] ; j = fail[u] ; fail[e] = c[i][j] ; cnt[e] += cnt[fail[e]] ; Q.push ( e ) ; } else c[i][u] = c[i][fail[u]] ; } } } void work () { int i , j , k , t , now , s , v , x , p , q ; for ( i = 0 ; i <= 11 ; i ++ ) for ( k = 1 ; k <= n ; k ++ ) for ( t = 0 ; t < tot ; t ++ ) add[i][k][t] = 0 ; for ( i = 1 ; i <= n ; i ++ ) for ( k = 0 ; k < tot ; k ++ ) { for ( v = 1 ; v <= len[i] ; v ++ ) { now = k ; for ( x = v ; x <= len[i] ; x ++ ) { p = s1[i][x] - ‘a‘ ; now = c[p][now] ; add[v][i][k] += cnt[now] ; } to[v][i][k] = now ; } } for ( i = 0 ; i <= l ; i ++ ) for ( j = 1 ; j <= n ;j ++ ) for ( k = 0 ; k < tot ; k ++ ) dp[i][j][k] = -1111111 ; for ( i = 1 ; i <= n ; i ++ ) { if ( len[i] > l ) continue ; now = 0 ; x = 0 ; for ( j = 1 ; j <= len[i] ; j ++ ) { k = s1[i][j] - ‘a‘ ; now = c[k][now] ; x += cnt[now] ; } dp[len[i]][i][now] = x ; } for ( i = 0 ; i < l ; i ++ ) for ( j = 1 ; j <= n ; j ++ ) for ( k = 0 ; k < tot ; k ++ ) { if ( dp[i][j][k] == -1111111 ) continue ; for ( t = 1 ; t <= n ; t ++ ) { s = vec[j][t].size () ; for ( x = 0 ; x < s ; x ++ ) { v = vec[j][t][x] ; p = i + inc[j][t][v] ; if ( p > l ) continue ; q = to[v][t][k] ; dp[p][t][q] = max ( dp[p][t][q] , dp[i][j][k] + add[v][t][k] ) ; } } } int ans = 0 ; for ( i = 1 ; i <= l ; i ++ ) for ( j = 1 ; j <= n ; j ++ ) for ( k = 0 ; k < tot ; k ++ ) ans = max ( ans , dp[i][j][k] ) ; printf ( "%d\n" , ans ) ; } void init () { tot = 0 ; new_node () ; } } ac ; void init () { ac.init () ; int i , j , k , t , l1 , l2 , flag ; for ( i = 1 ; i <= m ; i ++ ) ac.insert ( s2[i] + 1 ) ; ac.get_fail () ; for ( i = 1 ; i <= n ; i ++ ) len[i] = strlen( s1[i] + 1 ) ; for ( i = 1 ; i <= n ; i ++ ) for ( j = 1 ; j <= n ; j ++ ) { vec[i][j].clear () ; l1 = len[i] ; l2 = len[j] ; vec[i][j].push_back ( 1 ) ; inc[i][j][1] = l2 ; for ( k = l1 ; k >= 2 ; k -- ) { if ( l1 - k + 1 >= l2 ) break ; flag = 1 ; for ( t = k ; t <= l1 ; t ++ ) if ( s1[i][t] != s1[j][t-k+1] ) { flag = 0 ; break ; } if ( flag ) { vec[i][j].push_back ( l1 - k + 2 ) ; inc[i][j][l1-k+2] = l2 - l1 + k - 1 ; } } } ac.work () ; } int main () { int i , j , k ; while ( scanf ( "%d%d%d" , &n , &m , &l ) != EOF ) { for ( i = 1 ; i <= n ; i ++ ) scanf ( "%s" , s1[i] + 1 ) ; for ( i = 1 ; i <= m ; i ++ ) scanf ( "%s" , s2[i] + 1 ) ; init () ; } }
zoj 3535 Gao the String II(ac自动机+dp),布布扣,bubuko.com
原文:http://blog.csdn.net/no__stop/article/details/23175555
评论(0)