搞了半天,预处理各种错。。。
先说下题目意思吧,不好理解,当时比赛的时候是以为把得到的S和每个Bi去比,Bi的每一位如果正确对上了就算得1分,结果样例直接没过,就扔掉了
后来看了解题报告和标程,发现应该是S和每个Bi去比,当Bi是S的子串时才得1分
那么我们可以用自动机来进行DP,首先预处理对于每个Ai,可以和Aj的第几位开始的后缀进行link,然后剩下的自动机DP就比较简单了
定义dp[i][j][k]表示当前长度为i,且在自动机的状态j,并且这个状态是由link Ak转移过来的,我们对于Ak的每个可行的link单词进行枚举,转移即可
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<ctime>
using namespace std;
const int MAX=10000;
struct node
{
int next[26],fail,s;
};
node trie[MAX];
int idx,n,m,L,len[55];
char a[55][15];
vector<int>adj[55],start[55];
int dp[55][555][55];
int New()
{
for(int i=0;i<26;i++)
trie[idx].next[i]=-1;
trie[idx].s=0;
return idx++;
}
void insert(char str[])
{
int p=0,i=0,del;
while(str[i])
{
del=str[i]-'a';
if(trie[p].next[del]==-1)
trie[p].next[del]=New();
p=trie[p].next[del];
i++;
}
trie[p].s++;
}
void build_fail()
{
queue<int>que;
int fa,pre,i;
trie[0].fail=-1;
for(i=0;i<26;i++)
{
if(trie[0].next[i]!=-1)
{
trie[trie[0].next[i]].fail=0;
que.push(trie[0].next[i]);
}
else
trie[0].next[i]=0;
}
while(!que.empty())
{
fa=que.front();
que.pop();
trie[fa].s+=trie[trie[fa].fail].s;
for(i=0;i<26;i++)
{
pre=trie[fa].fail;
while(trie[pre].next[i]==-1)
pre=trie[pre].fail;
if(trie[fa].next[i]!=-1)
{
trie[trie[fa].next[i]].fail=trie[pre].next[i];
que.push(trie[fa].next[i]);
}
else
trie[fa].next[i]=trie[pre].next[i];
}
}
}
void init()
{
int i,j,k,l;
for(i=0;i<=n;i++)
{
adj[i].clear();
start[i].clear();
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
for(k=0;k<len[i]&&k<len[j];k++)
{
bool flag=true;
for(l=1;l<=k;l++)
{
if(a[i][len[i]-k+l-1]!=a[j][l-1])
{
flag=false;
break;
}
}
if(flag)
{
adj[i].push_back(j);
start[i].push_back(k);
}
}
}
}
for(i=1;i<=n;i++)
{
adj[0].push_back(i);
start[0].push_back(0);
}
}
void solve()
{
int res=0,i,j,k,l;
memset(dp,-1,sizeof(dp));
dp[0][0][0]=0;
for(int ll=0;ll<L;ll++)
{
for(i=0;i<idx;i++)
{
for(j=0;j<=n;j++)
{
if(dp[ll][i][j]==-1)
continue;
int xx=adj[j].size();
for(k=0;k<xx;k++)
{
int del=len[adj[j][k]]-start[j][k];
if(ll+del>L)
continue;
int ns=i;
int x=start[j][k],sum=0;
for(int y=0;y+x<len[adj[j][k]];y++)
{
int tmp=a[adj[j][k]][x+y]-'a';
ns=trie[ns].next[tmp];
sum+=trie[ns].s;
}
l=adj[j][k];
if(dp[ll+del][ns][l]<dp[ll][i][j]+sum)
{
dp[ll+del][ns][l]=dp[ll][i][j]+sum;
//cout<<ll<<" "<<i<<" "<<j<<" ->"<<ll+del<<" "<<ns<<" "<<l<<" sum="<<sum<<endl;
}
if(res<dp[ll+del][ns][l])
res=dp[ll+del][ns][l];
}
}
}
}
printf("%d\n",res);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out2.txt","w",stdout);
int i,j,k;
//int st=clock();
while(scanf("%d%d%d",&n,&m,&L)!=EOF)
{
idx=0;
New();
for(i=1;i<=n;i++)
{
scanf("%s",a[i]);
len[i]=strlen(a[i]);
}
for(i=1;i<=m;i++)
{
scanf("%s",a[n+1]);
insert(a[n+1]);
}
build_fail();
init();
solve();
//int en=clock();cout<<en-st<<"ms"<<endl;
}
return 0;
}