Keywords Search
版子题
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXNode (1000000)
#define Sigma_size (26)
class Aho_Corasick_Automata
{
public:
int ch[MAXNode][Sigma_size];
int v[MAXNode],siz;
// AC自动机
int f[MAXNode],last[MAXNode];
Aho_Corasick_Automata(int _siz=0):siz(_siz){MEM(ch) MEM(v) MEM(f) MEM(last)}
void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) MEM(f) MEM(last) }
int idx(char c){return c-'a';}
void insert(char *s) //val不为0 表示str末尾
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
}
u=ch[u][c];
}
v[u]++;
}
void getFail()
{
queue<int> q;
Rep(c,Sigma_size)
{
int u=ch[0][c];
if (u) q.push(u),last[u]=0;
}
while (!q.empty())
{
int r=q.front();q.pop(); //r--c-->u
Rep(c,Sigma_size)
{
int u=ch[r][c];
if (!u) {ch[r][c]=ch[f[r]][c]; continue;}
q.push(u);
f[u]=ch[f[r]][c];
last[u]=v[f[u]]?f[u]:last[f[u]];
}
}
}
int ans;
void print(int j) //打印全串中所有以j为末尾的str
{
if (j)
{
// printf("%d %d\n",j,v[j]);
ans+=v[j]; v[j]=0;
print(last[j]);
}
}
void find(char *s)
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
u=ch[u][c];
if (v[u]) print(u);
else if (last[u]) print(u);
}
}
}T;
char s[1000000+10];
int main()
{
// freopen("A.in","r",stdin);
// freopen(".out","w",stdout);
int t=read();
while(t--) {
int n=read();
T.mem();
For(i,n) {
scanf("%s",s);
T.insert(s);
}
T.getFail();
scanf("%s",s);
T.ans=0;
T.find(s);
cout<<T.ans<<endl;
}
return 0;
}
病毒侵袭
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN (500+10)
bool b[MAXN];
#define MAXNode (70000)
#define Sigma_size (100)
class Aho_Corasick_Automata
{
public:
int ch[MAXNode][Sigma_size];
int v[MAXNode],siz;
// AC自动机
int f[MAXNode],last[MAXNode];
Aho_Corasick_Automata(int _siz=0):siz(_siz){MEM(ch) MEM(v) MEM(f) MEM(last)}
void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) MEM(f) MEM(last) }
int idx(char c){return c-31;}
void insert(char *s,int val) //val不为0 表示str末尾
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
}
u=ch[u][c];
}
v[u]=val;
}
void getFail()
{
queue<int> q;
Rep(c,Sigma_size)
{
int u=ch[0][c];
if (u) q.push(u),last[u]=0;
}
while (!q.empty())
{
int r=q.front();q.pop(); //r--c-->u
Rep(c,Sigma_size)
{
int u=ch[r][c];
if (!u) {ch[r][c]=ch[f[r]][c]; continue;}
q.push(u);
f[u]=ch[f[r]][c];
last[u]=v[f[u]]?f[u]:last[f[u]];
}
}
}
void print(int j) //打印全串中所有以j为末尾的str
{
if (j)
{
if (v[j]) {
b[v[j]]=1; b[0]=1;
}
j=last[j];
}
}
void find(char *s)
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
u=ch[u][c];
if (v[u]) print(u);
else if (last[u]) print(u);
}
}
}T;
char s[10000+10];
int n,m;
int main()
{
// freopen("B.in","r",stdin);
// freopen(".out","w",stdout);
// cout<<sizeof(T)/1024<<endl;
while(scanf("%d\n",&n)!=EOF) {
T.mem();
For(i,n) {
gets(s);
T.insert(s,i);
}
T.getFail();
scanf("%d\n",&m);
int tot=0;
For(i,m) {
gets(s);
MEM(b)
T.find(s);
if(b[0]) {
++tot;
printf("web %d:",i);
For(i,n) if(b[i]) printf(" %d",i);
puts("");
}
}
printf("total: %d\n",tot);
}
return 0;
}
病毒侵袭持续中
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN (1000+10)
int b[MAXN];
#define MAXNode (50010)
#define Sigma_size (26)
class Aho_Corasick_Automata
{
public:
int ch[MAXNode][Sigma_size];
int v[MAXNode],siz;
// AC自动机
int f[MAXNode],last[MAXNode];
Aho_Corasick_Automata(int _siz=0):siz(_siz){MEM(ch) MEM(v) MEM(f) MEM(last)}
void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) MEM(f) MEM(last) }
int idx(char c){return c-'A';}
void insert(char *s,int val) //val不为0 表示str末尾
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
}
u=ch[u][c];
}
v[u]=val;
}
void getFail()
{
queue<int> q;
Rep(c,Sigma_size)
{
int u=ch[0][c];
if (u) q.push(u),last[u]=0;
}
while (!q.empty())
{
int r=q.front();q.pop(); //r--c-->u
Rep(c,Sigma_size)
{
int u=ch[r][c];
if (!u) {ch[r][c]=ch[f[r]][c]; continue;}
q.push(u);
f[u]=ch[f[r]][c];
last[u]=v[f[u]]?f[u]:last[f[u]];
}
}
}
void print(int j) //打印全串中所有以j为末尾的str
{
while (j)
{
if (v[j]) {
b[v[j]]++;
}
j=last[j];
}
}
void find(char *s)
{
int u=0,n=strlen(s);
Rep(i,n)
{
if (!isupper(s[i])) {
u=0;continue;
}
int c=idx(s[i]);
u=ch[u][c];
if (v[u]) print(u);
else if (last[u]) print(u);
}
}
}T;
char buf[MAXN][51];
char s[2000000+10];
int n,m;
int main()
{
// freopen("C.in","r",stdin);
// freopen(".out","w",stdout);
while(scanf("%d\n",&n)!=EOF) {
T.mem();
For(i,n) {
gets(buf[i]);
T.insert(buf[i],i);
}
T.getFail();
gets(s);
MEM(b)
T.find(s);
For(i,n) if (b[i]) {
printf("%s: %d\n",buf[i],b[i]);
}
}
return 0;
}
Word Puzzles
把查找串作为模式串,记得反过来
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN (1000+10)
int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
int n,m,q;
bool inside(int i,int j){return 0<=i&&i<n&&0<=j&&j<m;}
int ans[MAXN][3];
char buf[MAXN][MAXN];
char s[MAXN+10];
#define MAXNode (5000000)
#define Sigma_size (26)
class Aho_Corasick_Automata
{
public:
int ch[MAXNode][Sigma_size];
int v[MAXNode],siz;
// AC自动机
int f[MAXNode],last[MAXNode];
Aho_Corasick_Automata(int _siz=0):siz(_siz){MEM(ch) MEM(v) MEM(f) MEM(last)}
void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) MEM(f) MEM(last) }
int idx(char c){return c-'A';}
void insert(char *s,int val) //val不为0 表示str末尾
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
}
u=ch[u][c];
}
v[u]=val;
}
void getFail()
{
queue<int> q;
Rep(c,Sigma_size)
{
int u=ch[0][c];
if (u) q.push(u),last[u]=0;
}
while (!q.empty())
{
int r=q.front();q.pop(); //r--c-->u
Rep(c,Sigma_size)
{
int u=ch[r][c];
if (!u) {ch[r][c]=ch[f[r]][c]; continue;}
q.push(u);
f[u]=ch[f[r]][c];
last[u]=v[f[u]]?f[u]:last[f[u]];
}
}
}
void print(int j,int x,int y,int k) //打印全串中所有以j为末尾的str
{
while (j)
{
if (v[j]) {
ans[v[j]][0]=x;
ans[v[j]][1]=y;
ans[v[j]][2]=k;
}
j=last[j];
}
}
void find(int x,int y,int k)
{
int u=0;
while(inside(x,y))
{
char now=buf[x][y];
int c=idx(now);
u=ch[u][c];
if (v[u]) print(u,x,y,k);
else if (last[u]) print(u,x,y,k);
x+=dir[k][0],y+=dir[k][1];
}
}
}T;
int main()
{
// freopen("D.in","r",stdin);
// freopen(".out","w",stdout);
int t=read();
For(kcase,t) {
cin>>n>>m>>q;
T.mem();
Rep(i,n) {
scanf("%s",buf[i]);
}
For(i,q) {
scanf("%s",s);
reverse(s,s+strlen(s));
T.insert(s,i);
}
T.getFail();
Rep(i,m) {
T.find(n-1,i,0);
T.find(n-1,i,1);
T.find(n-1,i,7);
T.find(0,i,3);
T.find(0,i,4);
T.find(0,i,5);
}
Rep(i,n) {
T.find(i,0,1);
T.find(i,0,2);
T.find(i,0,3);
T.find(i,m-1,5);
T.find(i,m-1,6);
T.find(i,m-1,7);
}
For(i,q) {
if (ans[i][2]<4) ans[i][2]+=4; else ans[i][2]-=4;
printf("%d %d %c\n",ans[i][0],ans[i][1],'A'+ans[i][2]);
}
if(kcase<t) puts("");
}
return 0;
}
考研路茫茫——单词情结
长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?
不包含的可以用AC自动机建立转移矩阵A,答案=A+A^2+A^3+..+A^L的第一行的和
#include<cstdio>
#include<iostream>
#include<functional>
#include<vector>
#include<cstring>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--))
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define MAXN (100+10)
#define MAXNode (100+10)
#define Sigma_size (26)
#define pb push_back
typedef unsigned long long ll;
ll pow2(ll a,ll b)
{
if (b==1) return a;
if (b==0) return 1;
ll p=pow2(a,b/2);
p=p*p;
if (b&1) p=p*a;
return p;
}
struct M
{
int n,m;
ll a[MAXN][MAXN];
M(int _n=0){n=m=_n;MEM(a);}
M(int _n,int _m){n=_n,m=_m;MEM(a);}
void mem (int _n=0){n=m=_n;MEM(a);}
void mem (int _n,int _m){n=_n,m=_m;MEM(a);}
friend M operator*(M a,M b)
{
M c(a.n,b.m);
For(k,a.m)
For(i,a.n)
For(j,b.m)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j]);
return c;
}
friend M operator+(M a,M b)
{
For(i,a.n)
For(j,a.m)
a.a[i][j]=(a.a[i][j]+b.a[i][j]);
return a;
}
void make_I(int _n)
{
n=m=_n; MEM(a)
For(i,n) a[i][i]=1;
}
}A;
bool a3[1000000];
M pow222(M a,ll b)
{
M c;c.make_I(a.n);
int n=0;while (b) a3[++n]=b&1,b>>=1;
c=a; b=1;
M d=c;
ForD(i,n-1)
{
b=b*2+a3[i];
c=c*d+c;
d=d*d;
if (a3[i]) c=c*a+a,d=d*a;
}
return c;
}
ll pow222(ll a,ll b)
{
ll c=1;
int n=0;while (b) a3[++n]=b&1,b>>=1;
c=a; b=1;
ll d=c;
ForD(i,n-1)
{
b=b*2+a3[i];
c=c*d+c;
d=d*d;
if (a3[i]) c=c*a+a,d=d*a;
}
return c;
}
int n;
ll m;
class Trie
{
public:
int ch[MAXNode][Sigma_size],fa[MAXNode];
int fail[MAXNode],go[MAXNode][Sigma_size];
int siz;
bool tag[MAXNode];
void mem(){siz=0; MEM(tag) MEM(ch) MEM(fa) MEM(go) MEM(fail) }
int idx(char c){return c-'a';}
void insert(char *s)
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
fa[siz]=u;
}
u=ch[u][c];
}
tag[u]=1;
}
int q[MAXNode+10];
void make_fail()
{
int Head=1,Tail=1;
q[Head]=0;
For(i,siz) fail[i]=0;
while(Head<=Tail) {
int u=q[Head];
Rep(c,Sigma_size)
{
if (ch[u][c]) {
q[++Tail]=ch[u][c];
if (u==0) fail[ch[u][c]]=0;
else fail[ch[u][c]]=go[ fail[u] ][c];
go[u][c]=ch[u][c];
}
else {
go[u][c]=go[fail[u]][c];
}
}
Head++;
}
For(i,Tail) {
int now=q[i];
if (tag[fail[now]]) tag[now]=1;
}
int t=0;
vector<int> Q;
int h[MAXN]={0};
Rep(i,siz+1) {
if (!tag[i]) Q.pb(i),h[i]=++t;
}
A.mem(t);
For(i,t)
{
int now=Q[i-1];
Rep(j,Sigma_size) {
int v=go[now][j];
if (h[v]) A.a[i][h[v]]++;
}
}
}
}T;
char s[20];
ll L;
int main()
{
// freopen("P.in","r",stdin);
// freopen(".out","w",stdout);
while(cin>>n>>L) {
T.mem();
For(i,n) {
scanf("%s",s);
T.insert(s);
}
T.make_fail();
A=pow222(A,L);
ll ans=0;
ll tot=0;
tot=pow222(Sigma_size,L);
For(i,A.n) ans+=A.a[1][i];
cout<<tot-ans<<endl;
}
return 0;
}
Resource Archiver
题意:design a 01 string that contains all your resources (their occurrences can overlap), but none of the virus codes. To make your software smaller in size, the string should be as short as possible.
对每个单机在AC自动机上bfs一遍,求它到每个节点的最短距离,然后跑TSP。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<sstream>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int>
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %I64d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
For(j,m-1) cout<<a[i][j]<<' ';\
cout<<a[i][m]<<endl; \
}
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN (1000+10)
int b[MAXN];
int n,m;
int pos[MAXN];
int g[MAXN][MAXN];
#define MAXNode (4000000)
#define Sigma_size (2)
class Aho_Corasick_Automata
{
public:
int ch[MAXNode][Sigma_size];
int v[MAXNode],siz;
// AC自动机
int f[MAXNode],last[MAXNode];
Aho_Corasick_Automata(int _siz=0):siz(_siz){MEM(ch) MEM(v) MEM(f) MEM(last)}
void mem(int _siz=0){siz=_siz; MEM(ch) MEM(v) MEM(f) MEM(last) }
int idx(char c){return c-'0';}
void insert(char *s,int val) //val不为0 表示str末尾
{
int u=0,n=strlen(s);
Rep(i,n)
{
int c=idx(s[i]);
if (!ch[u][c])
{
++siz;
MEM(ch[siz]);
ch[u][c]=siz;
}
u=ch[u][c];
}
v[u]=val;
if (val!=-1) pos[val]=u;
}
void getFail()
{
queue<int> q;
Rep(c,Sigma_size)
{
int u=ch[0][c];
if (u) q.push(u),last[u]=0;
}
while (!q.empty())
{
int r=q.front();q.pop(); //r--c-->u
Rep(c,Sigma_size)
{
int u=ch[r][c];
if (!u) {ch[r][c]=ch[f[r]][c]; continue;}
q.push(u);
f[u]=ch[f[r]][c];
last[u]=v[f[u]]?f[u]:last[f[u]];
}
}
}
int dis[MAXNode];
void bfs(int u) {
queue<int> q;
MEMI(dis)
q.push(pos[u]); dis[pos[u]]=0;
while(!q.empty()) {
int u=q.front(); q.pop();
Rep(c,2) {
if (dis[ch[u][c]]==INF&&v[ch[u][c]]!=-1) {
dis[ch[u][c]]=dis[u]+1;
q.push(ch[u][c]);
}
}
}
For(i,n) g[u][i]=dis[pos[i]];
}
}T;
char s[100000+10];
int dp[1<<11][20],p2[20],len[20];
void work() {
Rep(i,n) p2[i+1]=1<<i;
int S=1<<n;
MEMI(dp)
For(i,n) dp[p2[i]][i]=len[i];
Rep(st,S) {
For(i,n) {
if (dp[st][i]!=INF) {
For(j,n) if (!(st&p2[j])) {
int ne=st|p2[j];
if (g[i][j]==INF) continue;
if (dp[ne][j]>dp[st][i]+g[i][j]) dp[ne][j]=dp[st][i]+g[i][j];
}
}
}
}
int ans=INF;
For(i,n) ans = min(ans, dp[S-1][i] );
cout<<ans<<endl;
}
int main()
{
// freopen("Q.in","r",stdin);
// freopen(".out","w",stdout);
while(scanf("%d%d\n",&n,&m)!=EOF&&n&&m) {
T.mem();
For(i,n) {
scanf("%s",s);
T.insert(s,i);
len[i]=strlen(s);
}
For(i,m) {
scanf("%s",s);
T.insert(s,-1);
}
T.getFail();
For(i,n) T.bfs(i);
work();
}
return 0;
}