zoukankan      html  css  js  c++  java
  • 【bzoj4136】[FJOI2015]带子串包含约束LCS问题

    题目描述:

    带有子串包含约束的最长公共子序列问题可以具体表述如下。
    给定2个长度分别为n和m的序列X和Y,以及一个子串包含约束集S。
    S中共有k个字符串S={S1,S2,…,Sk},其中字符串Si的长度为li,1≤i≤k。带有子串包含约束的最长公共子序列问题就是要找出X和Y的包含约束集S中所有字符串为其子串的最长公共子序列。
    例如,如果给定的序列X和Y分别为X=actaagacct, Y=gacctacctc,子串包含约束集S={ata, tact},则子序列actacct是X和Y的一个无约束的最长公共子序列,而包含约束集S中所有字符串为其子串的一个最长公共子序列是atact 。
    在本题中请特别关注子串与子序列的区别。字符串T=t1…tn的子串是一个形如T’=t1+i…tm+i的字符串,其中,0≤i,m+i≤n。例如,T=abcdefg,则bcd是T 的一个子串,而bce是T的一个子序列,但不是T 的子串。
    设计一个算法,找出给定序列X和Y带有子串包含约束S的最长公共子序列。

    输入:

    第1行中给出正整数n,m,k,m<300, n<300, k<6。n和m分别表示给定序列X和Y的长度。k表示子串包含约束集S中共有k个字符串。
    第2行中有k个整数li,0≤li≤300,1≤i≤k,分别表示子串包含约束集S中k个字符串的长度度。
    第3行和第4行分别给出序列X和Y 。
    接下来k行每行一个字符串Si

    输出:

    将计算出的X和Y带子串包含约束S的最长公共子序列的长度输出。

    样例输入:

    10 10 2
    3 4
    actaagacct
    gacctacctc
    ata
    tact

    样例输出:

    5

    题解:

    AC自动机+序列自动机+哈希+记忆化搜索

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    #ifdef WIN32
    	#define LL "%I64d"
    #else
    	#define LL "%lld"
    #endif
    
    #ifdef CT
    	#define debug(...) printf(__VA_ARGS__)
    	#define setfile() 
    #else
    	#define debug(...)
    	#define filename ""
    	#define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1 << 15], *S = B, *T = B;
    inline int FastIn()
    {
    	R char ch; R int cnt = 0; R bool minus = 0;
    	while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    	ch == '-' ? minus = 1 : cnt = ch - '0';
    	while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    	return minus ? -cnt : cnt;
    }
    #define maxn 310
    #define maxk 10
    #define maxcnt 30010
    int sl[maxk], trie[maxcnt][60], fail[maxcnt], t1[maxn][60], t2[maxn][60], len, cnt;
    char str1[maxn], str2[maxn], str[maxn];
    int end[maxcnt];
    inline void Insert(R int pos)
    {
    	R int now = 0;
    	for (R int i = 1; i <= len; i++)
    	{
    		R int c = str[i] - 'A';
    		if (!trie[now][c]) now = trie[now][c] = ++cnt;
    		else now = trie[now][c];
    	}
    	end[now] |= pos;
    }
    std::queue<int> q;
    inline void ACmach()
    {
    	fail[0] = 0;
    	for (R int i = 0; i < 60; ++i)
    		if (trie[0][i]) q.push(trie[0][i]);
    	while (!q.empty())
    	{
    		R int now = q.front(); q.pop(); end[now] |= end[fail[now]];
    		for (R int i = 0; i < 60; ++i)
    			if (!trie[now][i]) trie[now][i] = trie[fail[now]][i];
    			else
    			{
    				fail[trie[now][i]] = trie[fail[now]][i];
    				q.push(trie[now][i]);
    			}
    	}
    }
    #define hashsize 9991023
    #define INF 0x7fffffff
    struct Hashtable
    {
    	long long v; int dp;
    	Hashtable *next;
    }*last[hashsize], mem[hashsize], *tot = mem;
    inline Hashtable *Ha(R int a, R int b, R int now, R int s)
    {
    	R long long key = ((((long long)a<<9|b)<< 11|now)<< 6|s);
    	for (R Hashtable *pos = last[key % hashsize]; pos; pos = pos -> next) if (pos -> v == key) return pos;
    	*++tot = (Hashtable){key, 0,last[key % hashsize]};
    	last[key % hashsize] = tot;
    	return tot;
    }
    int full;
    int dfs(R int a, R int b, R int now, R int s)
    {
    	s |= end[now];
    	R Hashtable *key = Ha(a, b, now, s);	
    	if (key -> dp) return key->dp;
    	R int tmp = (s == full ? 0 : -INF);
    	for (R int i = 0; i < 60; ++i)
    		if (t1[a][i] && t2[b][i])
    		{
    			R int temp = dfs(t1[a][i], t2[b][i], trie[now][i], s);
    			cmax(tmp, temp);
    		}
    	return key->dp = tmp + 1;
    }
    int main()
    {
    	R int n, m, k;
    	scanf("%d %d %d
    ", &n, &m, &k);
    	full = (1 << k) - 1;
    	for (R int i = 0; i < k; ++i)
    		scanf("%d ", &sl[i]);
    	gets(str1 + 1);
    	gets(str2 + 1);
    	for (R int i = 0; i < k; ++i)
    	{
    		gets(str + 1);
    		len = sl[i];
    		Insert(1 << i);
    	}
    	ACmach();
    	memset(t1[n], 0, sizeof(t1[n]));
    	for (R int i = n; i; --i)
    	{
    		memcpy(t1[i - 1], t1[i], sizeof(t1[i]));
    		t1[i - 1][str1[i] - 'A'] = i;
    	}
    	memset(t2[m], 0, sizeof(t2[m]));
    	for (R int i = m; i; --i)
    	{
    		memcpy(t2[i - 1], t2[i], sizeof(t2[i]));
    		t2[i - 1][str2[i] - 'A'] = i;
    	}
    	R int ans = dfs(0, 0, 0, 0) - 1;
    	printf("%d
    ", dmax(ans, 0));
    	return 0;
    }
    /*
    10 10 2
    3 4
    actaagacct
    gacctacctc
    ata
    tact
    */



  • 相关阅读:
    ObjectiveC分类
    显示时间格式
    js模拟签名
    安装卸载homebrew
    NSFastEnumeration
    拼接音频
    在Orchard模块中访问模块本地的AppSettings
    重装证书
    msysgit中文问题
    Apple Push Notification service
  • 原文地址:https://www.cnblogs.com/cocottt/p/6765015.html
Copyright © 2011-2022 走看看