题目描述:
带有子串包含约束的最长公共子序列问题可以具体表述如下。
给定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
【题解】
2015带子串包含约束LCS问题
//by Woodstock
/*
显然对于子序列的玄学要求应该用ac自动机匹配 然后同【bzoj1030】[JSOI2007]文本生成器等利用ac自动机+动态规划解决字符串计数的经典问题相似(不要问我为什么 反正我就是这么觉得的)
借鉴上述题目的状态表示方法 不难想到四维状态f[i][j][k][t]表示x串匹配到第i为,y串匹配到第j位,自动机上为第k位,当前满足s集合中的哪些串(用二进制压缩)
转移:朴素转移 (i,j)-->{(i+1,j),(i,j+1),(i+1,j+1(same))}
300*300*1500*32我的天复杂度高了不止一点点 时间和空间都炸了
*/
//=========================================================================考场上一段长时间的思考
/*
如何解决?直观想法是利用滚动数组节省空间 然后卡一卡时间就。。(毕竟人要有信仰
事实证明 还是比较好打的
然后我傻逼的把i,j同时滚动调了一个多小时都没调出来 再见
*/
//========================================================================一段长时间的不知道干什么
/*
看了一下wwx大爷的题解(其实什么都没有说,永远都是一句话题解 再见
讲了两个时间上的优化(what 这就完了 果然大神都不屑于讲现场A的题
1.转移时枚举下一个字符,转移到2个串最近的位置(wwx大爷原话 对不起我说不清楚)
2.预处理出g[i][j]表示无视子串包含约束的情况下X的后缀i和Y的后缀j的最长公共子序列
当当前已经满足所有约束时直接用g更新最优解并扔掉当前状态
当当前状态加上g后仍劣于当前最优解时扔掉当前状态(不过这个没啥用)
看完这个 就想到用队列实现动态规划
*/
//=======================================================================一个周天
/*
打了一下队列(3.66k) 发现居然会 T两个点 空间还要开到450M+(什么鬼
由于需要反复入队更新答案造成 (顺便orz战神 记忆化搜索1k代码秒过(记忆化状态表示不同
然而我 并不想写 底层优化 再见
那就假装我AC了
*/
//======================================================================
/*
之前一直觉得要打平衡树才能不造成反复入队
下午突发奇想 把队列改成优先队列
多了1k代码 队列大小也和我预期的2*2*1500*32差不多 (其实显然不需要这么多2333
*/
//=====================================================================
/*
历时三天(周六周一周二)终于把这个玄学的题目AC了
总的来讲 这题还是比较好想 程序也比较好写(即使是接近200行的代码也可以十分的模块化)
状态表示和转移方法都会影响到程序实现起来的难易
还是比较符合我的胃口的233(一开始就会有想法 但还是觉得有难度 然后慢慢思考不断完善就可以解决
实在不像某些坑爹动态规划和数学题结论题(一开始想得到的人就秒a 其他人想破脑袋都不会
总之就是我太菜了
*/
/*
:Zu
iB@B@i iGM;
i@@B@@@B2 7B@B@B@.
@@@@B@B@B@u iM@B@B@B@BL
B@B@N OB@@@BY F@@@B@BMM@B@O
E@B@B .O@B@B@: :BB@@@B@0U7FB@B@
:@B@B. .@B@B@O YB@B@B@OSYJjuU@B@B
@B@B5 rB@B@B7 u@B@B@BNuYj1UFuuB@B@i
2@@@@ N@@@@M 5B@B@BBkjYU252511JMB@B1
@@B@i :@@@B@ J@B@@@MFLju515151FUJE@B@M
F@B@B @@@B@, iB@B@@B1YJ12F152F1511JPB@B@
@B@B: EB@@@. . .::::.... O@@B@BSLuU51F151F15152u2@B@B
L@@B@ 0B@B@ .:rLuk8MB@B@B@B@B@B@@@B@B@B@B@@@@@B@B@G@@@B@PuY2251F1F151F1F1Fu2B@B@.
B@@@Y @B@BB2MB@B@@@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@B@BMujU52F1F151525151511Y@@@Bi
@B@B @B@@@B@@@B@@@B@@@BBZNuu7ri:,,.. B@B@0kN88MB@BEYu252525151F252F1F15UJM@B@J
JB@B@ 0@B@@BE17i,. @B@BUvJYJLJjUj125151F152525151F1F55YO@@BX
B@B@v .B@B@jUU5252221212F2515251F15252F1F2JE@B@O
@B@B. @B@BFJF1F2F2F2F2515151F152F251F5515YEB@B@
.B@@@ B@B@ELU52F152F251525151515252F1F2F2JX@B@B
v@B@B vB@B@uj255F15151F2F15252515151F1S15JNB@B@
PB@BX @B@BBYu2F1F1F2F15152F2515151F152F1jP@B@B
B@B@v @B@BBjJu5251S25151F15251515151F15JNB@@B
BB@@: @B@B@XYL2UF151F15151F2F251F2F251j0@B@B
B@B@i @B@B@BPJJJU251111152525152121Uuv1B@B@B.
FB@B@B vB@B@B@ZSjjLujUu1U1u2u2uuJJLj2XZ@@@B@@:
@B@B@u v@@@B@B@MOXkuujuJjJuu55qEMB@@@B@B@B@Bi
:@B@B@ :P@B@B@@@B@B@B@B@B@B@@@B@B@B@U L@B@Bi
r@B@BE .vO@@B@B@B@B@B@B@B@B@MU: Y@B@B,
r@B@Bu ,rL52F15Uv;: k@B@B
,@@@BJ :BB1 B@B@M
. @B@BP .5X, @B@B@Bv B@B@:
r@B@@@@Mu: BB@B@ .B@B@ .8B@B@B@BF, uB@B@
7B@B@B@@@B@B8B@@@ 7B@B@M iMB@B@@@B@Xr. @B@B:
.:iJZ@B@B@B@@@k :5@B@B@X ,SB@B@B@B@B@BPYi.. P@B@Z
.rB@B@B@BMi r@BONE0EM@B@B@B@B@: i5@B@@@B@B@B@@@B@ :B@B@
@B@B@B@B@O @B@B@B@@@@@B@@@5. :LEB@B@B@B@B: @B@B
iB@B@ iB@B7 :ZM@B@B@BO57, .:i B@B@ii2OOk
M@B@2 @B@B@B@B@@@
@B@B. .jOM07 .UB@B@B@B@@@B@r
.B@B@ MB@B@@@B7 M@B@B@B@Bi
r@B@B 7O@@BJ SB@B@B@B@B. PB@BP@@B@
uB@BO @@@B@B@Br 8@@@B@B@B@: @B@B
S@@@F @B@B@B@B@@ .B@B@B@B@B ZB@Bk
SB@B1 B@B@B@B@@@ 5@B@B@7 B@B@.
v@B@k .B@@@@@B@r 2@B@B
vB@B@:r7; vBB@BF @B@B:
:71Z@B@B@B@B@B@B@BM 8B@BE
v@B@B@B@@@B@B@@@B@B@B@r @B@B@B@@@:
@B@B@B@BMFJi: MB@BJ .B@B@B@B@@@B@Ov
.7: :@B@@ ;@@B@B@B@B@@@@2
B@B@v Z@@@B ,LMB@B@B@r
rB@B@ B@B@B .EB@B@
@B@BM .B@B@B .M@j
@B@B1 rB@@@M
:@B@Bj i8B@B@B@B@B@Bu GB@B@F
i@B@BX M@@@B@@@B@B@B@B@ :@@@B@i
i@B@B@ 7B@BFri:,:ivOB@X ,B@B@BM
.@B@B@L ,BB@@@Bi
qB@B@@7 jB@B@B@L
:B@B@B@2. JB@@@B@Bv
:@B@B@B@u. ,FB@B@B@BP,
.S@B@B@B@0r :jBB@B@B@@@B.
:P@B@B@B@BOv, .:7kO@B@B@B@@@B@B@@@
.vBB@B@B@@@B@ONjr:, ,:rYXE@B@@@@@@@B@@@B@MEuri@@@B.
J@B@B@B@B@B@@@@@B@B@B@@BM8ENFPFUuUuuuU5XFP0GOMB@B@B@B@B@@@B@B@B@B@B@BMX2vr::::,iB@B@
rB@BM71NMB@B@B@@@B@@@@@B@B@B@B@B@@@B@@@B@@@B@B@B@B@@@B@@@B@BBZqULri:::::::;;rr:r@B@B.
u@B@E.,::::iirvLJFFN0OOMM@B@BMO@B@B@@@B@B@@@@@B@MuL2JY77ii:::::::ii;irrrr7r7rr:iB@B@.
1B@BZ,;rr;;ii:i::::::::::::,.:Z@@B@B@quLYJqB@B@B@q: ::::ii;;rrrr7rrr7r7rrii::::u@B@B.
F@@@P.::i;rrrrrrrrrr;r;r;ri,7@@@@@u. L@@B@BL,rr7r7r7r7rrrrrrii::::iLSBB@B@B@:
OB@B@EF7;::,::ii;ir;rrrrr;:7@B@BO ..... N@@@BL:rrrrri;ii:::::irLF8B@B@B@B@B@Bv
Z@B@@@B@B@MZ5J7ri:::,:::::,@B@@E .,,:,,.. N@B@B,.:::::i;7j2NO@B@B@B@B@B@E:F@B@P
@B@BBB@@@B@B@B@@@B@MOqX1u7UB@B@ .:,,,,.. ,. B@B@k1NOM@B@B@@@B@B@B@B@BSi iB@B@
iB@B@ iYG@@@@B@@@B@B@@@B@B@B@M ,,:,,., rB@B@5. ZB@B@B@B@@@B@@@B@BBF7, @B@B
B@B@u :rjSO@@B@B@B@B@B@ .,,,.,. r@@@@@B8M@B@B@B@BOFu;:. B@B@i
S@B@B @B@@r ....... :5@B@B@B@B 5B@BB
L@@@B, 7@B@Bi . . . .B@B@Bu @B@@.
G@B@B; q@B@Bk 7@B@BM G@B@@
B@B@B: L@B@B@O7. .rOB@B@Bu B@B@B
qB@M ZB@B@@@B@@@B@B@B@Z .B@@@B
7MB@B@B@B@B@Mv S@8.
,:7ri.
... . .. ..
:7FB2 B@B r. :@B. L@@ @B ,.,.,..
.@@@@B@B@B@@@B OB@ L@BO j@@ B@B@B@B@B@B@@@B@ 0PXSXSSJMB@L5FXSSuNB@u5SXSXXZi ,,,,., iB@B@@@@ B@B@B@B@@@B@M
@BOurE@B F@B M@@M: O@i :::,:,,.. :@B@O @@@@B@@@B@B@B@B@B@@@B@B@@@B@B2 @B@B@B .@E .B@ .,,.... @BL..
rBB rB@ B@Y vEFL@BNuF2uj u@BX .B5 F5 B@ B@ BE O@. q@
v@B :@@ E@B@B@B@B@@@ XB@P k1jujjSMG0qPqMB@BBB@B@B@v @B B@ @0 @B iLUUuY. ZB,
@B@B@B@B@B@B@@@B@B@B@B@B@B@B@B L@u .@B @@@ @B@B@BBOMOM@E2PXqkLi:vi,. @@ B@ Bq 0B, B@@@@@Y N@:
ii::,.S@B .:,:,.:@@i.::,. ,i @B. JBq 0@1 iJ r@Y @@ @B @B @1 B@ MB .B7 NB:
7B@ @@ :@7 :@@ B@i.:::::: MBO ,::::i MB@ B@O E@B7 B@ B@ Bk @B: O@ ,@r k@,
r@M r5 @Bu 5@Bk M@v @B B@B@B@B@B@@@B@B@B@: 5B@. BE r@@F @B @B @E @B OB. :B7 PB:
,:MB@B@B@B@. U@B .@@@. .@B PB8 E@q ;i .O; J B@ B@ B8 :@q E@ .@r k@,
B@B@@@B@BPu7, B@ uB@5 v@@S B@ E@E UEkk5277J1YvrBB@r7LYrLUFFkkqE: @B MB @Z B@ PBi YBv NB:
0Mui. LBB MB@BB 7B@B@: OBO @B@B@B@B@O@B@B@B@B@O@B@B@@@B@; @@ @@ .@0 @B P@B@B@v N@:
v@B qB@Br iXi B@BP 8@O 7@@ iBX @Bi @B@B@B @B7v@BG @B: OB:
JB@ JB@B51@B M@@ LB@:rB@Bi GBM ,B@BL r@8 vB@8, .@@ 5@ .@Gq@Bv , Z@:
L@B PB@B@J M@B. @@7 i@B@ 0@7 B@M iO@@@r YBB r@B@BY. :. :@q MB:
G@N5S@BB Z@S. P@BZ.uB@ ,B@B7 UB@B@@@B: OB@@@5 j@B L@B@B@, iBB FMq1OB@
2B@B@MJ :@B@B@: Sj NFXF5i ,@u qB@ .Y. i@O Y@B@BZ.
.. :Ur
k :..,, r ii v: ir .L E ..,,:,iivv :.. ,F : u .:iu1
.u5BjL:i@@rB@ @k :Bi 7@Bu. uMiNBuL ,@SSuEB5qZUO8 :qN1uM@7777: :v@B i2X@vS@ Bv @ 7B7v7i:
.@ ,B UB v@: BX Li O O7u 2 O. 28 .Br,S :B. r7vvrE@7vjLL :B Yiv@:7@j BqiB 7B
:LuB27i8 uG .B@r..:ii,,F@: JO1@ 0;F B7@: Lr rOui k. M1::2@:ii@ ,BqF i7@,78 ON.. rB@Y7Z@
2 @r NY55E: r:@B77rBr :2@.v1ik .@., uM ,OG:Bq Br @5::2@,:iB, ,, @ :;vBiii @8ir vJY7 Mu
B 8E7 B 0O .@ @i :@B7 Mi 5B5: .P: i,BF j i2 5Yi:F@:ii8 .B7G 77J@rvJ: B7 @ P7 BPG
:@k@. @v7rO7 2B B B, i@ @ iJujLr@G77uJU .7r7iNBi;7rr uBL :.:B .. .@ B B BBJ
@i 1ZXqkEq0X0 7@P qk0B5 BE 7@ B B7 ZXF2U8@j11k0r YB.rSuuuGjUkX 1P @PXv@i X@:
.,. .
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
const long long Limithash=10000007,limitque=100007;
int i,j,k,m,n,len[10],num,pd,x,y,ans;
int nextx[305][53],nexty[305][53],g[305][305];
int tot,sum[limitque],hash[Limithash];
long long q[limitque];
bool same[305][305];
int fail[1505],last[1505],tree[1505][54],que[1505];
char sx[305],sy[305],s[305];
int c[305][305][53];
void Swap(int x,int y)
{
long long hashpos1=q[x]%Limithash;
while (true)
{
if (hash[hashpos1]==x) break;hashpos1++;
if (hashpos1==Limithash) hashpos1=0;
if (hashpos1==q[x]%Limithash) printf("!!!!!!1");
}
long long hashpos2=q[y]%Limithash;
while (true)
{
if (hash[hashpos2]==y) break;hashpos2++;
if (hashpos2==Limithash) hashpos2=0;
if (hashpos2==q[y]%Limithash) printf("!!!!!!2");
}
swap(hash[hashpos1],hash[hashpos2]);
swap(sum[x],sum[y]);swap(q[x],q[y]);
}
void up()
{
for (int x=tot;x!=1;)
if (q[x]<q[x>>1]) Swap(x,x>>1),x>>=1;else break;
}
void down()
{
for (int x=1;(x<<1)<=tot;)
{
int y=x<<1;
if (y+1<=tot && q[y+1]<q[y]) y++;
if (q[y]<q[x]) Swap(x,y),x=y;else break;
}
}
void hash_in(int i,int j,int k,int t,int data)
{
long long s=((((long long)i<<9|j)<< 11|k)<< 6|t);
long long hashpos=s%Limithash;
while (hash[hashpos])
{
if (q[hash[hashpos]]==s)
{
sum[hash[hashpos]]=max(sum[hash[hashpos]],data);
return;
}
hashpos++;
if (hashpos==Limithash) hashpos=0;
if (hashpos==s%Limithash) printf("!!!!!!3");
}
tot++;hash[hashpos]=tot;q[tot]=s; sum[tot]=data;
up();
}
void hash_out(int h)
{
long long hashpos=q[h]%Limithash;
while (true)
{
if (hash[hashpos]==h)
{
sum[h]=0;q[h]=0;hash[hashpos]=0;
return;
}
hashpos++;
if (hashpos==Limithash) hashpos=0;
if (hashpos==q[h]%Limithash) printf("!!!!!!4");
}
}
void ins(int x)
{
int now=1;
for (int i=1;i<=len[x];i++)
{
int j;
if (s[i]>='a'&&s[i]<='z') j=s[i]-'a'+1;else j=s[i]-'A'+27;
if (!tree[now][j]) tree[now][j]=++num;
now=tree[now][j];
}
last[now]|=1<<(x-1);
}
void getfail()
{
int h=0,t=1;que[1]=1;
for (;h<t;)
{
int now=que[++h];last[now]|=last[fail[now]];
for (int i=1;i<=52;i++)
if (tree[now][i]) fail[que[++t]=tree[now][i]]=tree[fail[now]][i];
else tree[now][i]=tree[fail[now]][i];
}
}
void work()
{
long long i,j,k,t;
int nowsum;
hash_in(0,0,1,0,0);
for (;tot;)
{
t=q[1] & 63;k=(q[1]>>6) & 2047;j=(q[1]>>17) & 511;i=q[1]>>26;nowsum=sum[1];
Swap(1,tot);hash_out(tot);tot--;down();
if (nowsum+g[i+1][j+1]<=ans) continue;
for (int chr=1;chr<=c[i][j][0];chr++)
{
int o=c[i][j][chr];int now=tree[k][o];int t1=t|last[now];
hash_in(nextx[i][o],nexty[j][o],now,t1,nowsum+1);
}
if (t==pd) ans=max(ans,nowsum+g[i+1][j+1]);
}
}
void find_next()
{
int last[53];
memset(last,0,sizeof last);
for (int i=n;i>=0;i--)
{
int j;
if (sx[i]>='a'&&sx[i]<='z') j=sx[i]-'a'+1;else j=sx[i]-'A'+27;
for (int k=1;k<=52;k++) nextx[i][k]=last[k];
last[j]=i;
}
memset(last,0,sizeof last);
for (int i=m;i>=0;i--)
{
int j;
if (sy[i]>='a'&&sy[i]<='z') j=sy[i]-'a'+1;else j=sy[i]-'A'+27;
for (int k=1;k<=52;k++) nexty[i][k]=last[k];
last[j]=i;
}
for (int i=0;i<=n;i++)
for (int j=0;j<=m;j++)
for (int o=1;o<=52;o++)
if (nextx[i][o] && nexty[j][o]) c[i][j][++c[i][j][0]]=o;
}
void get_g()
{
for (int i=n;i;i--)
for (int j=m;j;j--)
{
g[i][j]=max(g[i+1][j],g[i][j+1]);
if (sx[i]==sy[j]) g[i][j]=max(g[i][j],g[i+1][j+1]+1);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (sx[i]==sy[j]) same[i][j]=1;
}
void init()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=k;i++) scanf("%d",&len[i]);scanf("\n");
for (int i=1;i<=52;i++) tree[0][i]=1;
num=1;
scanf("%s\n",sx+1);scanf("%s\n",sy+1);
for (int i=1;i<=k;i++)
{
scanf("%s\n",s+1);
ins(i);
}
pd=(1<<k)-1;
}
int main()
{
freopen("in8.in","r",stdin);
init();
getfail();
find_next();
get_g();
work();
printf("%d",ans);
}