前言:
本题为作业
题目描述
AKAAKAKAKKAAKK....如果我们在键盘上打出一个AK串(只由字符A和K组成的固定位数的字符串),就可以AK全场么?
不可以,有些AK串不允许出现!
现在给定整数n和m,n表示AK串的位数,m表示所有n位AK串中不允许出现的前缀,请输出合法的n位AK串的个数。
输入格式
两行,第一行是两个整数n和m
接下来的m行,每行一个AK串前缀,保证合法且长度在1至n之间,以及这m个前缀互不相同。
输出格式
一行,一个整数,表示允许出现的AK串的个数。
样例输入
3 2 KKK AK
样例输出
5
问题提示
对于70%的数据,n<=10, m<=10;
对于100%的数据,n<=18, m<=18;
解题思路
我们先枚举,再状态压缩优化
可以把A当作1
K当作0
AK串就变成了一个二进制数
可以状态压缩了
AC完整代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
bool vis[300000];
void showBit(int x)
{
for(int i=n-1;i>=0;i--)
{
cout<<((x>>i)&1);//输出一个二进制
}
cout<<endl;
}
int main()
{
string s;
int cnt=0;
cin>>n>>m;
int all=1<<n;
for(int i=1;i<=m;i++)//循环遍历
{
cin>>s;//如题目输入
int u=1<<(n-s.size());
int num=0;
for(int j=0;j<s.size();j++)
{
if(s[j]=='A')//如果是 A
{
num<<=1;//左移一位
num+=1;//把移出来的位改为1
}
else
{
num<<=1;//把移出来的位改为0
}
}
num<<=(n-s.size());
for(int j=0;j<u;j++)
{
if(!vis[num+j])
{
cnt++;
vis[num+j]=1;
}
}
}
cout<<all-cnt;//输出
return 0;
}