题目: http://acm.hdu.edu.cn/showproblem.php?pid=3247
题意:
给定n个串,将他们放在一个串s中,可以重叠;
给定m个串,要求s中不能出现这m个串;
问s最小多长。
分析:
两篇很好的题解:
https://blog.csdn.net/woshi250hua/article/details/8021283
https://www.cnblogs.com/Konjakmoyu/p/5665802.html
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long llong;
const int tmax=6e4+5;
int n,m,pos[15],cost[15][15],dis[tmax],dp[1100][15],length[15];
queue<int> Q;
struct AC{
int cnt,ch[tmax][2],f[tmax],val[tmax],last[tmax];
void init()
{
cnt=0;
memset(ch,0,sizeof(ch));
memset(f,0,sizeof(f));
memset(val,-1,sizeof(val));
memset(last,0,sizeof(last));
return;
}
int insert(char *s,bool tag)
{
int len=strlen(s),u=0,id;
for(int i=0;i<len;i++)
{
id=s[i]-'0';
if(ch[u][id]==0)
ch[u][id]=++cnt;
u=ch[u][id];
}
val[u]=tag;
if(!tag) return u;
return 0;
}
void getfail()
{
int x,u,v;
Q.push(0);
while(!Q.empty())
{
x=Q.front();Q.pop();
for(int i=0;i<=1;i++)
{
u=ch[x][i];
if(!u)
{
ch[x][i]=ch[f[x]][i];
continue;
}
Q.push(u);
if(x==0) continue;
v=f[x];
while(v&&!ch[v][i]) v=f[v];
f[u]=ch[v][i];
last[u]=val[f[u]]!=-1?f[u]:last[f[u]];
}
}
return;
}
void bfs()
{
int u,v;
for(int i=1;i<=n;i++)
{
memset(dis,-1,sizeof(dis));
dis[pos[i]]=0;
Q.push(pos[i]);
while(!Q.empty())
{
u=Q.front();Q.pop();
for(int j=0;j<=1;j++)
{
v=ch[u][j];
if(dis[v]!=-1||val[v]==1) continue;
dis[v]=dis[u]+1;
Q.push(v);
}
}
for(int j=1;j<=n;j++)
cost[i][j]=dis[pos[j]];
}
return;
}
void cal()
{
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=n;i++)
dp[1<<(i-1)][i]=length[i];
int top=(1<<n)-1;
for(int s=1;s<=top;s++)
for(int i=1;i<=n;i++)
{
if((s&(1<<(i-1)))==0) continue;
for(int j=1;j<=n;j++)
if((s&(1<<(j-1)))==0)
dp[s+(1<<(j-1))][j]=min(dp[s+(1<<(j-1))][j],dp[s][i]+cost[i][j]);
}
int ans=0x3f3f3f3f;
for(int i=1;i<=n;i++)
ans=min(ans,dp[top][i]);
printf("%d\n",ans);
return;
}
}ac;
int main()
{
char s[tmax];
while(1)
{
ac.init();
scanf("%d%d",&n,&m);
if(n==0&&m==0) break;
for(int i=1;i<=n;i++)
{
scanf("%s",s);
length[i]=strlen(s);
pos[i]=ac.insert(s,0);
}
for(int i=1;i<=m;i++)
{
scanf("%s",s);
ac.insert(s,1);
}
ac.getfail();
ac.bfs();
ac.cal();
//ac.test();
}
return 0;
}