题目链接:BZOJ - 1559

题目分析

将给定的串建成AC自动机,然后在AC自动机上状压DP。

转移边就是Father -> Son 或 Now -> Fail。

f[i][j][k] ,表示到了字符串第 i 位,在AC自动机的第 j 个节点上,状态为 k 的方案数。

状态 k 是一个二进制压缩的,表示已经包含了哪些给定串的整数。

然后...输出方案....这个太麻烦了...我是从最后状态DFS向前反推。

另外的问题是我写的AC自动机DP无法正确处理给定串存在串 A 包含串 B 的情况,所以我必须将被其他给定串包含的给定串忽略。

要去掉所有被其他某个给定串包含的给定串。需要在建完Fail之后从每个节点向Fail一直走到Root,将一路上的所有节点都设定为不是给定串。

当然要记录一下某个节点沿Fail到Root的路径已经被处理的话就 break。

我刚开始写的代码只能处理一个串是另一个串前缀或后缀的情况,被包含在中间的情况不能处理,但是仍然在BZOJ AC了。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue> using namespace std; const int MaxL = 15, MaxM = 15, MaxC = 27, MaxN = 25 + 5, MaxNode = 255 + 5; typedef long long LL; int n, m, l, Index, Tot, MT, Top; LL Ans;
LL f[MaxN][MaxNode][1024 + 15]; char S[MaxL]; struct Str
{
char str[MaxN];
} Sol[50], DS; bool Cmp(Str s1, Str s2)
{
for (int i = 0; i < n; ++i)
{
if (s1.str[i] == s2.str[i]) continue;
return s1.str[i] < s2.str[i];
}
return false;
} struct Trie
{
int Num, ID, c, isStr;
bool Ed;
Trie *Child[MaxC], *Fail;
} TA[MaxNode], *P = TA, *Root, *Zero; void Insert(char *S, int l)
{
Trie *Now = Root;
int t;
for (int i = 1; i <= l; ++i)
{
t = S[i] - 'a';
if (Now -> Child[t] == NULL)
{
++P; P -> Num = 0; P -> ID = ++Tot; P -> c = t;
Now -> Child[t] = P;
}
Now = Now -> Child[t];
}
Now -> isStr = 1;
} void Init_AC()
{
Index = 0; Tot = 0;
Zero = P; //ID : 0
Root = ++P; Root -> ID = ++Tot; //ID : 1
for (int i = 0; i < 26; ++i) Zero -> Child[i] = Root;
Zero -> Fail = NULL;
for (int i = 0; i < 26; ++i) Root -> Child[i] = NULL;
Root -> Fail = Zero;
} queue<Trie *> Q; void Build_Fail()
{
while (!Q.empty()) Q.pop();
Q.push(Root);
Trie *Now, *Temp;
while (!Q.empty())
{
Now = Q.front(); Q.pop();
for (int i = 0; i < 26; ++i)
{
if (Now -> Child[i] == NULL) Now -> Child[i] = Now -> Fail -> Child[i];
else
{
Now -> Child[i] -> Fail = Now -> Fail -> Child[i];
Q.push(Now -> Child[i]);
}
}
}
for (Trie *j = TA; ; ++j)
{
Temp = j -> Fail;
while (Temp != NULL && Temp != Root && Temp != Zero)
{
if (Temp -> Ed) break;
Temp -> Ed = true;
Temp -> isStr = -1;
Temp = Temp -> Fail;
}
if (j == P) break;
}
for (Trie *j = TA; ; ++j)
{
if (j -> isStr == 1) j -> Num = ++Index;
else j -> Num = 0;
if (j == P) break;
}
} void DP()
{
f[0][1][0] = 1;
MT = (1 << Index) - 1;
for (int i = 0; i <= n; ++i)
for (int j = 0; j <= Tot; ++j)
for (int k = 0; k <= MT; ++k)
if (f[i][j][k])
{
for (int t = 0; t < 26; ++t)
{
if (TA[j].Child[t] -> Num == 0) f[i + 1][TA[j].Child[t] -> ID][k] += f[i][j][k];
else f[i + 1][TA[j].Child[t] -> ID][k | (1 << (TA[j].Child[t] -> Num - 1))] += f[i][j][k];
}
}
Ans = 0;
for (int i = 1; i <= Tot; ++i) Ans += f[n][i][MT];
} void DFS(int l, int x, int y, int t)
{
//printf("Begin %d %d %d %c\n", l, x, y, t + 'a');
DS.str[l - 1] = 'a' + t;
if (l == 1)
{
Sol[++Top] = DS;
return;
}
for (int i = 1; i <= Tot; ++i)
if (f[l - 1][i][y] && TA[i].Child[t] -> ID == x)
{
if (i == 1) for (int j = 0; j < 26; ++j) DFS(l - 1, i, y, j);
else DFS(l - 1, i, y, TA[i].c);
}
int yy;
if (TA[x].Num != 0)
{
yy = y - (1 << (TA[x].Num - 1));
for (int i = 1; i <= Tot; ++i)
if (f[l - 1][i][yy] && TA[i].Child[t] -> ID == x)
{
if (i == 1) for (int j = 0; j < 26; ++j) DFS(l - 1, i, yy, j);
else DFS(l - 1, i, yy, TA[i].c);
}
}
//printf("End %d %d %d %c\n", l, x, y, t + 'a');
} void Get_Sol()
{
Top = 0;
for (int i = 1; i <= Tot; ++i)
if (f[n][i][MT])
{
if (i == 1)
{
for (int j = 0; j < 26; ++j)
DFS(n, i, MT, j);
}
else DFS(n, i, MT, TA[i].c);
}
} int main()
{
scanf("%d%d", &n, &m);
Init_AC();
Index = 0;
for (int i = 1; i <= m; ++i)
{
scanf("%s", S + 1);
l = strlen(S + 1);
Insert(S, l);
}
Build_Fail();
DP();
printf("%lld\n", Ans);
if (Ans <= 42)
{
Get_Sol();
sort(Sol + 1, Sol + Ans + 1, Cmp);
for (int i = 1; i <= Ans; ++i)
{
Sol[i].str[n] = 0;
printf("%s\n", Sol[i].str);
}
}
return 0;
}

  

[BZOJ 1559] [JSOI2009] 密码 【AC自动机DP】的更多相关文章

  1. BZOJ 1559: [JSOI2009]密码( AC自动机 + 状压dp )

    建AC自动机后, dp(x, y, s)表示当前长度为x, 在结点y, 包括的串的状态为s的方案数, 转移就在自动机上走就行了. 对于输出方案, 必定是由给出的串组成(因为<=42), 所以直接 ...

  2. BZOJ 1559 JSOI2009 密码 状压dp+AC自动机+搜索

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1559 分析: 这个题意真的是很**啊!!!直接说每一个字符串至少出现一次不就好了吗... ...

  3. BZOJ1559[JSOI2009]密码——AC自动机+DP+搜索

    题目描述 输入 输出 样例输入 10 2 hello world 样例输出 2 helloworld worldhello 提示 这题算是一个套路题了,多个串求都包含它们的长为L的串的方案数. 显然是 ...

  4. [JSOI2009]密码 [AC自动机]

    题面 bzoj luogu 首先看到这题就知道随便暴枚 只要是多项式算法都能过 先常规建AC自动机 注意被别的单词包含的单词没有存在的价值 剩余单词状压 大力dp f[长度][节点编号][状态] \( ...

  5. [BZOJ1559][JSOI2009]密码(AC自动机)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1559 2009年的省选题虽然比起现在简单了不少,但对我来说还是很有挑战性的. 首先对于这种多串匹配问 ...

  6. [bzoj] 1030 文本生成器 || AC自动机+dp

    原题 给出n个字符串,求随机生成一个m长度的字符串,有多少个是可辨识的(即出现了n个字符串中的任意字符串) 正难则反 求有多少个不可辨识的,26^m-不可辨识即为答案 f[i][j]表示填到第i个字符 ...

  7. [BZOJ 3530] [Sdoi2014] 数数 【AC自动机+DP】

    题目链接:BZOJ - 3530 题目分析 明显是 AC自动机+DP,外加数位统计. WZY 神犇出的良心省选题,然而去年我太弱..比现在还要弱得多.. 其实现在做这道题,我自己也没想出完整解法.. ...

  8. bzoj 1030 [JSOI2007]文本生成器(AC自动机+DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1030 [题意] 给n个小串,随机构造一个长为m的大串,一个串合法当且仅当包含一个或多个 ...

  9. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

随机推荐

  1. CFileDialog的使用方法简单介绍

    CFileDialog文件选择对话框的使用:首先构造一个对象并提供对应的參数,构造函数原型例如以下: CFileDialog::CFileDialog( BOOL bOpenFileDialog, L ...

  2. Android开发优化之——对Bitmap的内存优化

    http://blog.csdn.net/arui319/article/details/7953690 在Android应用里,最耗费内存的就是图片资源.而且在Android系统中,读取位图Bitm ...

  3. UVA10518 - How Many Calls?(矩阵高速幂)

    UVA10518 - How Many Calls?(矩阵高速幂) 题目链接 题目大意:给你fibonacci数列怎么求的.然后问你求f(n) = f(n - 1) + f(n - 2)须要多少次调用 ...

  4. .net缓存应用与分析

    在 ASP.NET 提供的许多特性中,相比 ASP.NET 的所有其他特性,缓存对应用程序的性能具有最大的潜在影响,利用缓存和其他机制,ASP.NET 开发人员可以接受使用开销很大的控件(例如,Dat ...

  5. CentOS 6.7平台Hadoop 1.2.1环境搭建

    本教程使用Vultr的VPS搭建,主要实现HDFS和MapReduce两个功能. master.hadoop - 45.32.90.100 slave1.hadoop - 45.32.92.47 sl ...

  6. Java基础--继承方法调用顺序

    最近因为面试的原因,回过头来复习基础的知识,都忘光了,准备买本面试书回来啃. 我先把自己测试的结论总结写出来,以后忘记再来看看 如果b类继承自a类,在main方法中new出b的对象(不带参数),那么他 ...

  7. jquery mobile入门资料

    由于项目中用到了,就去看了一下视频,然后进一步的找找资源,最后自己再总结一遍!(就是动手操作一遍,不论你感觉多简单,只有动手之后,你才有可能有收获) 当然如果你喜欢看文档可以到官网仔细研究,不过喜欢快 ...

  8. H TML5 之 (1) 初识HTML5

    新特性 HTML5 中的一些有趣的新特性: 用于绘画的 canvas 元素 用于媒介回放的 video 和 audio 元素 对本地离线存储的更好的支持 新的特殊内容元素,比如 article.foo ...

  9. 从腾讯QQgame高性能服务器集群架构看“分而治之”与“自治”等分布式架构设计原则

    转载:http://space.itpub.net/17007506/viewspace-616852 腾讯QQGame游戏同时在线的玩家数量极其庞大,为了方便组织玩家组队游戏,腾讯设置了大量游戏室( ...

  10. Play - js/css concatenation & minify

    1. Css We’ll use LESS CSS, all less sources are defined in the app/assets, and they will be compiled ...