题目大意:有个人想破解他邻居的密码,他邻居告诉了一些关于这个密码的信息,并且给他一个单词集合,他用这些信息判断一下最少有多少种密码。
1->, 所有的密码都是有小写字母组成。
2->,密码的长度是 n (1<= n <=25)。
3->,密码至少包含 k 种字符集里面的单词。
 
比如,给集合{"she", "he"},单词长度是3,最少包含两个单词的密码,很明显只能是“she”(题目表述的不清楚)。
 
分析:因为要统计记录到达每个点时候经过多少种不同的单词,所以需要用一种方法来保存这些信息,开一个数组来判重貌似是个很容易想到的办法,不过考虑时间复杂度的问题,建议还是不要这么干,因为字符集合的数量很少,只有10,所以我们可以使用状态压缩来保存这些信息,而且转移状态时候也很方便操作,不过有点需要注意,一定要把遍历子节点放在最内层循环,这样再遍历每一种状态的时候发先有0的情况可以continue一下,否则超时超的哇哇的.......
 
代码如下:
==========================================================================
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; const int MAXN = ;
const int MaxSon = ;
const int Mod = ;
const int oo = 1e9+; struct Ac_Trie
{
int next[MAXN][MaxSon];
int Fail[MAXN], End[MAXN];
int cnt, root; int newnode()
{
for(int i=; i<MaxSon; i++)
next[cnt][i] = -;
Fail[cnt] = End[cnt] = false; return cnt++;
}
void InIt()
{
cnt = ;
root = newnode();
} void Insert(char s[], int t)
{
int now = root; for(int i=; s[i]; i++)
{
int k = s[i]-'a'; if(next[now][k] == -)
next[now][k] = newnode();
now = next[now][k];
} End[now] = <<t;
}
void GetFial()
{
queue<int>Q;
int now = root; for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = root;
else
{
Fail[next[now][i]] = root;
Q.push(next[now][i]);
}
} while(Q.size())
{
now = Q.front();
Q.pop(); for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = next[Fail[now]][i];
else
{
Fail[next[now][i]] = next[Fail[now]][i];
Q.push(next[now][i]);
}
} End[now] |= End[Fail[now]];
}
}
};
Ac_Trie ac; int Find(int i)
{
int k=; while(i)
{
if(i % )
k++;
i /= ;
} return k;
} int main()
{
int N, M, K; int sum[] ={}; for(int i=; i<; i++)
sum[i] = Find(i); while(scanf("%d%d%d", &N, &M, &K), N+M+K)
{
char s[MAXN];
ac.InIt(); for(int i=; i<M; i++)
{
scanf("%s", s);
ac.Insert(s, i);
} ac.GetFial(); int dp[][MAXN][] = {}, op=, Len = <<M;
dp[][][] = ; while(N--)
{
memset(dp[op], , sizeof(dp[op])); for(int i=; i<ac.cnt; i++)
for(int k=; k<Len; k++)
{///把k放中间优化一下...否则超时
if(dp[op^][i][k] == )
continue; for(int j=; j<MaxSon; j++)
{
(dp[op][ac.next[i][j]][k|ac.End[i]] += dp[op^][i][k])%=Mod;
}
} op ^= ;
} int ans = ; for(int i=; i<ac.cnt; i++)
for(int j=; j<Len; j++)
{
if(sum[j] >= K || sum[ac.End[i]|j] >= K)
{
ans += dp[op^][i][j];
ans %= Mod;
}
} printf("%d\n", ans);
} return ;
}

Wireless Password - HDU 2825(ac自动机+状态压缩)的更多相关文章

  1. hdu 2825(ac自动机+状态压缩dp)

    题意:容易理解... 分析:在做这道题之前我做了hdu 4057,都是同一种类型的题,因为题中给的模式串的个数最多只能为10个,所以我们就很容易想到用状态压缩来做,但是开始的时候我的代码超时了dp时我 ...

  2. HDU 4511 (AC自动机+状态压缩DP)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...

  3. hdu 4057(ac自动机+状态压缩dp)

    题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...

  4. hdu 3341(ac自动机+状态压缩)

    题意:容易理解... 思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A.T.C.G ...

  5. hdu 2825 aC自动机+状压dp

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

  6. HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )

    模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...

  7. HDU 4758 Walk Through Squares( AC自动机 + 状态压缩DP )

    题意:给你两个串A,B, 问一个串长为M+N且包含A和B且恰好包含M个R的字符串有多少种组合方式,所有字符串中均只含有字符L和R. dp[i][j][k][S]表示串长为i,有j个R,在自动机中的状态 ...

  8. POJ 3691 (AC自动机+状态压缩DP)

    题目链接:  http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...

  9. bzoj1195 神奇的ac自动机+状态压缩dp

    /* 难的不是ac自动机,是状态压缩dp 之前做了一两题类似题目,感觉理解的还不够透彻 */ #include<iostream> #include<cstdio> #incl ...

随机推荐

  1. 深入了解java集群技术

    原文源自:http://blog.csdn.net/happyangelling/article/details/6413584 序言 越来越多的关键应用运行在J2EE(Java 2, Enterpr ...

  2. WCF存储图片到指定文件夹下

    string path = System.IO.Directory.GetCurrentDirectory() + @"\POIImages\"; Guid imgid = Gui ...

  3. Singleton设计模式的一种见解

    单实例Singleton设计模式可能是被讨论和使用的最广泛的一个设计模式了,这可能也是面试中问得最多的一个设计模式了.这个设计模式主要目的是想在整个系统中只能出现一个类的实例.这样做当然是有必然的,比 ...

  4. Java封装的与当前时间比较,得到多少年,多少月,多少天前,多少小时前,多小分钟前

    public class CalendarCal { /**  * 与当前时间比较,得到多少年,多少月,多少天前,多少小时前,多小分钟前  *   * @param calendar  *       ...

  5. 10集合:List<T>,Dictionary<K,V>

    List<T>泛型集合 List<T>是C#中一种快捷.易于使用的泛型集合类型,使用泛型编程为编写面向对象程序增加了极大的效率和灵活性.   1.List<T>用法 ...

  6. Python:标准数据类型6种

    #!/usr/bin/python3 #python的基本语法和数据类型 #python3中 一行有多个语句,用分号分割(;) print("aaa") ;print(" ...

  7. Java多线程:Semaphore

    Semaphore为并发包中提供用于控制某资源同时可以被几个线程访问的类 实例代码: // 允许2个线程同时访问 final Semaphore semaphore = new Semaphore(2 ...

  8. [转载]python os.path模块

    os.path模块主要用于文件的属性获取,在编程中经常用到,以下是该模块的几种常用方法.更多的方法可以去查看官方文档:http://docs.python.org/library/os.path.ht ...

  9. One-day-学习笔记-商品成交时发送短信

    个人学习笔记(one) 根据需求:商品成交时发送短信 html代码省略..... Model代码省略..... /* * --------------------------------------- ...

  10. 关于pcre正则表达式库libpcre

    gcc 4.8中已经包含了std regex的头文件 可是没有实现,所以链接是失败的 gcc 4.9完整的支持了c++ 11的regex. 在4.9以前,可以寻求boost的regex. 不过,我更熟 ...