您的位置:首页 > 大数据 > 人工智能

Wireless Password [ 2009 Multi-University Training Contest 1 - Host by TJU ]

2011-08-03 22:38 453 查看
链接: http://acm.hdu.edu.cn/showproblem.php?pid=2825

分类: AC自动机 + 状态压缩 + DP

题意:问构成长度为 N 的字符串中包含已知串中至少 K 个的总个数

分析:

AC自动机部分:采用朴素的构建即可,注意记录当前节点的状态(status)即到达当前节点时包含的已知串状态

状态压缩部分:采用位存储当前节点包含已知串状态,第 i 位为1,表示包含第 i 个字符串

DP部分:建立dp[ i ][ j ][ k ],表示长度为 i,状态到达第 j 个结点,且包含已知串状态为 k 时的个数,显然有 dp[ 0 ][ 0 ][ 0 ] = 1,最后的结果是 ans = sum{ dp[ N ][ j ][ k ] | Ones( k ) >= K },其中Ones( k )表示 k 的二进制数中包含 1 的个数。

假设处理长度为i,当前结点为 j,且包含已知串状态为 k,且即将转移到某一结点指针 p,那么有 

dp[ i ][ p->idx ][ p->status | k ] = dp[ i ][ p->idx ][ p->status | k ] + dp[ i - 1 ][ j ][ k ]

参考程序

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long i64d;

const int MOD = 20090717;
const int maxQ = 10086;
const int maxC = 26;
const int maxE = 1024;
const int maxS = 1024;
const int maxN = 30;

struct node
{
node *fal, *cld[maxC];
int status, idx;
};

static node *Q[maxQ]; static int Qs, Qt;
static node E[maxE]; static int nE;
static node *root;

inline void init()
{
nE = -1; root = &E[++nE];
root->status = 0, root->idx = 0;
root->fal = 0; memset(root->cld, 0, sizeof(root->cld));
}

inline void insert(char str[], int idx)
{
static int pos;
static node *curNode; curNode = root;
for(int i = 0; str[i]; ++i) {
pos = str[i] - 'a';
if( curNode->cld[pos] != 0) curNode = curNode->cld[pos];
else {
curNode->cld[pos] = &E[++nE];
curNode = curNode->cld[pos];

curNode->fal = 0; memset(curNode->cld, 0, sizeof(curNode->cld));
curNode->status = 0, curNode->idx = nE;
}
}
curNode->status |= (0x1 << idx);
}

inline void acmation()
{
root->fal = 0; // root's fail
static int pos; Qs = Qt = 0;
Q[Qt++] = root; static node *cur;
while( Qs != Qt ) {
cur = Q[Qs++];

for(int i = 0; i < maxC; ++i) {
pos = i; // change if possible
if( cur->cld[pos] != 0 ) {
if( cur == root ) cur->cld[pos]->fal = root;
else {
cur->cld[pos]->fal = cur->fal->cld[pos];

cur->cld[pos]->status |= cur->cld[pos]->fal->status;
}

Q[Qt++] = cur->cld[pos];
} else {
if( cur == root ) cur->cld[pos] = root;
else cur->cld[pos] = cur->fal->cld[pos];
}
}
}
}

static int N, M, K;
static char subString[30];
static int dp[maxN][maxE][maxS];

static int Ones[maxS];

inline void getOnes()
{
static int val;
for(int i = 0; i < maxS; ++i) {
Ones[i] = 0; val = i;
while( val ) ++Ones[i], val &= (val - 1);
}
}

int main()
{
//freopen("data.in", "r", stdin);
getOnes();
while( scanf("%d %d %d", &N, &M, &K) == 3 ) {
if( N == 0 && M == 0 && K == 0 ) break;

init();
for(int i = 0; i < M; ++i) {
scanf("%s", subString);
insert(subString, i);
}
acmation();

for(int i = 0; i <= N; ++i) {
for(int j = 0; j <= nE; ++j) {
for(int k = 0; k < (0x1 << M); ++k) {
dp[i][j][k] = 0;
}
}
}
dp[0][0][0] = 1;

static int nC; static node *p;
for(int i = 1; i <= N; ++i) {
for(int j = 0; j <= nE; ++j) {
for(int k = 0; k < (0x1 << M); ++k) {
if( dp[i - 1][j][k] != 0 ) {
for(nC = 0; nC < maxC; ++nC) {
p = E[j].cld[nC];
dp[i][p->idx][k | p->status] += dp[i - 1][j][k];
dp[i][p->idx][k | p->status] %= MOD;
}
}
}
}
}

int ans = 0;
for(int j = 0; j <= nE; ++j) {
for(int k = 0; k < (0x1 << M); ++k) {
if( Ones[k] < K ) continue;

ans += dp
[j][k];
ans %= MOD;
}
}

printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐