pid=2825">http://acm.hdu.edu.cn/showproblem.php?

pid=2825

Wireless Password
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4560    Accepted Submission(s): 1381
Problem Description
Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless network in the building. Liyuan did not know the password of the network, but he got some important information from his neighbor. He knew the password consists only of lowercase
letters 'a'-'z', and he knew the length of the password. Furthermore, he got a magic word set, and his neighbor told him that the password included at least k words of the magic word set (the k words in the password possibly overlapping).



For instance, say that you know that the password is 3 characters long, and the magic word set includes 'she' and 'he'. Then the possible password is only 'she'.



Liyuan wants to know whether the information is enough to reduce the number of possible passwords. To answer this, please help him write a program that determines the number of possible passwords.
 
Input
There will be several data sets. Each data set will begin with a line with three integers n m k. n is the length of the password (1<=n<=25), m is the number of the words in the magic word set(0<=m<=10), and the number k denotes that the password included at
least k words of the magic set. This is followed by m lines, each containing a word of the magic set, each word consists of between 1 and 10 lowercase letters 'a'-'z'. End of input will be marked by a line with n=0 m=0 k=0, which should not be processed.
 
Output
For each test case, please output the number of possible passwords MOD 20090717.
 
Sample Input
10 2 2
hello
world
4 1 1
icpc
10 0 0
0 0 0
 
Sample Output
2
1
14195065
 
Source
 

题意:

给出m个模式串。要求构造一长度为n的文本串,至少包含k种模式串,求有多少种可能的模式串。

分析:

m个模式串构建AC自己主动机。然后要在这AC自己主动机中走n步。至少经过k个单词结点。由于m<=10,显然能够用状压表示已经有哪几个单词结点。用dp[i][j][k]表示走了i步到AC自己主动机中的第j个结点,单词状态为k。由计数原理可推出状态转移方程:dp[i][j][k]=sum(dp[i-1][last_j][last_k]),last_j表示能够抵达第j个结点的上一个结点。last_k表示上一步的状态;由于第i步仅仅和第i-1步有关。所以能够用滚动数组优化空间。

/*
*
* Author : fcbruce <fcbruce8964@gmail.com>
*
* Time : Thu 20 Nov 2014 10:01:45 AM CST
*
*/
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10 #ifdef _WIN32
#define lld "%I64d"
#else
#define lld "%lld"
#endif #define maxm
#define maxn 255 using namespace std; const int mod = 20090717; int dp[2][maxn][1024]; inline int add(int a,int b)
{
return (a+b)%mod;
} int q[maxn]; const int maxsize = 26;
struct ACauto
{
int ch[maxn][maxsize];
int val[maxn],nex[maxn],last[maxn];
int sz; ACauto()
{
memset(ch[0],0,sizeof ch[0]);
val[0]=0;
sz=1;
} void clear()
{
memset(ch[0],0,sizeof ch[0]);
val[0]=0;
sz=1;
} int idx(char c)
{
return c-'a';
} void insert(const char *s,int v)
{
int u=0;
for (int i=0;s[i]!='\0';i++)
{
int c=idx(s[i]);
if (ch[u][c]==0)
{
memset(ch[sz],0,sizeof ch[sz]);
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
} void get_fail()
{
int f=0,r=-1;
nex[0]=0;
for (int c=0;c<maxsize;c++)
{
int u=ch[0][c];
if (u!=0)
{
nex[u]=0;
q[++r]=u;
last[u]=0;
}
} while (f<=r)
{
int x=q[f++];
for (int c=0;c<maxsize;c++)
{
int u=ch[x][c];
if (u==0)
{
ch[x][c]=ch[nex[x]][c];
continue;
}
q[++r]=u;
int v=nex[x];
nex[u]=ch[v][c];
val[u]|=val[nex[u]];
}
}
} int calc(int x)
{
int cnt=0;
for (int i=0;i<32;i++)
if (x&(1<<i)) cnt++;
return cnt;
} int DP(int l,int m,int k)
{
memset(dp,0,sizeof dp);
dp[0][0][0]=1;
int x=1;
for (int i=0;i<l;i++,x^=1)
{
memset(dp[x],0,sizeof dp[x]);
for (int j=0;j<sz;j++)
{
for (int s=0;s<m;s++)
{
if (dp[x^1][j][s]==0) continue;
for (int c=0;c<maxsize;c++)
{
int &cur=dp[x][ch[j][c]][s|val[ch[j][c]]];
cur=add(cur,dp[x^1][j][s]);
}
}
}
} int total=0; for (int i=0;i<m;i++)
{
if (calc(i)<k) continue;
for (int j=0;j<sz;j++)
total=add(total,dp[x^1][j][i]);
} return total;
}
}acauto; char str[16]; int main()
{
#ifdef FCBRUCE
freopen("/home/fcbruce/code/t","r",stdin);
#endif // FCBRUCE int n,m,k; while (scanf("%d%d%d",&n,&m,&k),n||m||k)
{
acauto.clear();
for (int i=0;i<m;i++)
{
scanf("%s",str);
acauto.insert(str,1<<i);
} acauto.get_fail(); printf("%d\n",acauto.DP(n,1<<m,k));
} return 0;
}

HDU 2825 Wireless Password (AC自己主动机,DP)的更多相关文章

  1. HDU - 2825 Wireless Password(AC自己主动机+DP)

    Description Liyuan lives in a old apartment. One day, he suddenly found that there was a wireless ne ...

  2. hdu 2825 Wireless Password(ac自己主动机&amp;dp)

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. Hdu 2457 DNA repair (ac自己主动机+dp)

    题目大意: 改动文本串的上的字符,使之不出现上面出现的串.问最少改动多少个. 思路分析: dp[i][j]表示如今 i 个字符改变成了字典树上的 j 节点. 然后顺着自己主动机一直转移方程. 注意合法 ...

  4. HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )

    题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 162 ...

  5. HDU 2825 Wireless Password(AC自动机+DP)

    题目链接 做题, #include <cstdio> #include <string> #include <cstring> using namespace st ...

  6. POJ 3691 &amp; HDU 2457 DNA repair (AC自己主动机,DP)

    http://poj.org/problem?id=3691 http://acm.hdu.edu.cn/showproblem.php?pid=2457 DNA repair Time Limit: ...

  7. HDU 2896 病毒侵袭 (AC自己主动机)

    pid=2896">http://acm.hdu.edu.cn/showproblem.php?pid=2896 病毒侵袭 Time Limit: 2000/1000 MS (Java ...

  8. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

  9. HDU 2896 病毒侵袭 AC自己主动机题解

    本题是在text里面查找key word的增强版.由于这里有多个text. 那么就不能够简单把Trie的叶子标志记录改动成-1进行加速了,能够使用其它技术.我直接使用个vis数组记录已经訪问过的节点, ...

随机推荐

  1. perl学习之:正则表达式

  2. PyQt5(2)、垃圾分类小程序(2)——初代窗口程序可执行文件

    又是一天时间(又没做大作业).今天的心路历程:(1)前端后端怎么连接?(2)后端数据库插数据(3)完全没用上之前的字典反查法(4)突然发现面向对象编程其实很好用,甚至越用越上瘾(5)QLineEdit ...

  3. 基础训练 FJ的字符串

    FJ的字符串 #include<iostream> #include<string.h> using namespace std; int main(){ string str ...

  4. redis 内存管理与数据淘汰机制(转载)

    原文地址:http://www.jianshu.com/p/2f14bc570563?from=jiantop.com 最大内存设置 默认情况下,在32位OS中,Redis最大使用3GB的内存,在64 ...

  5. DocView mode 0 -- 介绍

          DocView mode,可作为主模式也可以作为minor mode,可以用来阅读DVI(ps后缀),PDF,OpenDocument(libreoffice文档),微软的doc.支持截取 ...

  6. 二分查找与 bisect 模块

    Python 的列表(list)内部实现是一个数组,也就是一个线性表.在列表中查找元素可以使用 list.index() 方法,其时间复杂度为O(n).对于大数据量,则可以用二分查找进行优化.二分查找 ...

  7. iOS 唯一标示符 卸载后安装值不变

    Vindor标示符 (IDFV-identifierForVendor) 这种叫法也是在iOS 6中新增的,不过获取这个IDFV的新方法被添加在已有的UIDevice类中.跟advertisingId ...

  8. 去掉WordPress顶部工具条

    WordPress为了方便管理员,或者登陆用户快速的从前台进入后台来管理网站,在WordPress网站顶部强制加入了一个工具条(admin bar),而且默认是对所有登陆用户都显示的,有时候看着挺烦心 ...

  9. Windows同步阿里云时间

    Ctrl+R打开cmd命令框 输入:gpedit.msc 计算机配置”—“管理模版”—“系统”—“Windows 时间服务”—“时间提供程序”—“配置 Windows NTP 客户端 双击打开配置 W ...

  10. BZOJ 4161 Shlw loves matrixI ——特征多项式

    矩阵乘法递推的新姿势. 叉姐论文里有讲到 利用特征多项式进行递推,然后可以做到k^2logn #include <cstdio> #include <cstring> #inc ...