每个奶酪上面n位二进制,含有0,1,*三种符号,现在有m个奶酪,我们需要用一个机器来clear这些奶酪,clear的条件就是机器上的n位二进制与奶酪上面的二进制相同,但是*可以代替0或1,所以这样的话只要两个奶酪的只有一个位置不同的话,还是可以用同一个改变clear两个奶酪了,所以这样就建边。然后就是最小边覆盖。
/*****************************************
Author :Crazy_AC(JamesQi)
Time :2015
File Name :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1 << 11;
int g[N][N];
int num[N*2];
int n, m;
int top;
char s[20];
void input() {
top = 0;
for (int i = 1;i <= m;++i) {
scanf("%s",s);
int ans = 0;
for (int j = 0;j < n;++j) {
if (s[j] == '*') ans = ans * 2 + 0;
else ans = ans * 2 + s[j] - '0';
}
num[++top] = ans;
ans = 0;
for (int j = 0;j < n;++j) {
if (s[j] == '*') ans = ans * 2 + 1;
else ans = ans * 2 + s[j] - '0';
}
num[++top] = ans;
}
sort(num + 1,num + 1 + top);
// for (int i = 1;i <= top;++i)
// printf("%4d",num[i]);
int up = 1;
for (int i = 2;i <= top;++i) {
if (num[i] != num[up]) {
num[++up] = num[i];
}
}
top = up;
// cout << "top = " << top << endl;
memset(g, 0,sizeof g);
for (int i = 1;i <= top;++i) {
for (int j = i + 1;j <= top;++j) {
int t = num[i] ^ num[j];
if (t && (t&(t-1))==0)
g[i][j] = g[j][i] = 1;
}
}
// for (int i = 1;i <= top;++i) {
// for (int j = 1;j <= top;++j)
// printf("%2d",g[i][j]);
// puts("");
// }
}
int cx[N], cy[N];
bool vis[N];
bool dfs(int u) {
for (int i = 1;i <= top;++i) {
if (!vis[i] && g[u][i]) {
vis[i] = true;
if (cy[i] == 0 || dfs(cy[i])) {
cy[i] = u;
cx[u] = i;
return true;
}
}
}
return false;
}
int hungary() {
memset(cx, 0,sizeof cx);
memset(cy, 0,sizeof cy);
int ans = 0;
for (int i = 1;i <= top;++i) {
memset(vis, false,sizeof vis);
if (dfs(i)) ans++;
}
return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(~scanf("%d%d",&n,&m) && (n + m)) {
input();
int ans = hungary();
// cout << top << endl;
printf("%d\n",top - ans/2);
}
return 0;
}