http://poj.org/problem?id=1625

题意:

给出一些单词,求长度为m的串不包含这些单词的个数。

思路:

这道题和HDU 2243和POJ 2778是一样的,不同的是这道题不取模,所以不可以用矩阵快速幂,必须使用高精度,所以这里用滚动dp解决即可。

高精度的写法参考了kuangbin巨巨的模板。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn=+; int n, m, num, p, len;
map<char,int> mp;
char s[]; struct Trie
{
int son[];
int cnt;
int fail;
}t[*]; struct Matrix
{
int mat[][], n;
Matrix(){}
Matrix(int _n)
{
n=_n;
for(int i=;i<n;i++)
for(int j=;j<n;j++)
mat[i][j]=;
}
}; void init(int x)
{
t[x].fail=;
t[x].cnt=;
memset(t[x].son,,sizeof(t[x].son));
} void trie(char *s)
{
int n=strlen(s);
int x=;
for(int i=;i<n;i++)
{
int c=mp[s[i]];
if(!t[x].son[c])
{
num++;
init(num);
t[x].son[c]=num;
}
x=t[x].son[c];
}
t[x].cnt=;
} void buildAC()
{
queue<int> Q;
for(int i=;i<=len;i++) if(t[].son[i]) Q.push(t[].son[i]);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
int fail=t[x].fail;
for(int i=;i<=len;i++)
{ int y=t[x].son[i];
if(y)
{
t[y].fail=t[fail].son[i];
t[y].cnt|=t[t[fail].son[i]].cnt; //这儿很重要,这个标记需要传递
Q.push(y);
}
else t[x].son[i]=t[fail].son[i];
}
}
} Matrix getMatrix()
{
Matrix c=Matrix(num+);
for(int i=;i<=num;i++)
{
for(int j=;j<=len;j++)
{
if(t[t[i].son[j]].cnt==) c.mat[i][t[i].son[j]]++;
}
}
return c;
} /******************************高精度算法************************************/
struct BigInt
{
const static int mod = ;
const static int DLEN = ;
int a[],len;
BigInt()
{
memset(a,,sizeof(a));
len = ;
}
BigInt(int v)
{
memset(a,,sizeof(a));
len = ;
do
{
a[len++] = v%mod;
v /= mod;
}while(v);
}
BigInt(const char s[])
{
memset(a,,sizeof(a));
int L = strlen(s);
len = L/DLEN;
if(L%DLEN)len++;
int index = ;
for(int i = L-;i >= ;i -= DLEN)
{
int t = ;
int k = i - DLEN + ;
if(k < )k = ;
for(int j = k;j <= i;j++)
t = t* + s[j] - '';
a[index++] = t;
}
}
BigInt operator +(const BigInt &b)const
{
BigInt res;
res.len = max(len,b.len);
for(int i = ;i <= res.len;i++)
res.a[i] = ;
for(int i = ;i < res.len;i++)
{
res.a[i] += ((i < len)?a[i]:)+((i < b.len)?b.a[i]:);
res.a[i+] += res.a[i]/mod;
res.a[i] %= mod;
}
if(res.a[res.len] > )res.len++;
return res;
}
BigInt operator *(const BigInt &b)const
{
BigInt res;
for(int i = ; i < len;i++)
{
int up = ;
for(int j = ;j < b.len;j++)
{
int temp = a[i]*b.a[j] + res.a[i+j] + up;
res.a[i+j] = temp%mod;
up = temp/mod;
}
if(up != )
res.a[i + b.len] = up;
}
res.len = len + b.len;
while(res.a[res.len - ] == &&res.len > )res.len--;
return res;
}
void output()
{
printf("%d",a[len-]);
for(int i = len-;i >= ;i--)
printf("%04d",a[i]);
printf("\n");
}
};
/*************************************************************************/ BigInt dp[][]; int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&m,&p);
mp.clear();
scanf("%s",s+);
len=strlen(s+);
for(int i=;i<=len;i++) mp[s[i]]=i;
for(int i=;i<=p;i++)
{
scanf("%s",s);
trie(s);
}
buildAC();
Matrix a=getMatrix(); //滚动数组实现
int now = ;
dp[now][] = ;
for(int i=;i<a.n;i++) dp[now][i] = ;
for(int i=;i<m;i++)
{
now^=;
for(int j=;j<a.n;j++) dp[now][j] = ;
for(int j=;j<a.n;j++)
for(int k=;k<a.n;k++)
if(a.mat[j][k] > ) dp[now][k] = dp[now][k]+dp[now^][j]*a.mat[j][k];
}
BigInt ans = ;
for(int i = ;i < a.n;i++)
ans = ans + dp[now][i];
ans.output();
return ;
}

POJ 1625 Censored!(AC自动机+高精度+dp)的更多相关文章

  1. POJ 1625 Censored! [AC自动机 高精度]

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 9793   Accepted: 2686 Descrip ...

  2. POJ 1625 Censored!(AC自动机+DP+高精度)

    Censored! Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 6956   Accepted: 1887 Descrip ...

  3. poj 1625 (AC自动机好模版,大数好模版)

    题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...

  4. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  5. 关于AC自动机和DP的联系

    首先是描述个大概.不说一些特殊的DP 或者借用矩阵来状态转移 (这些本质都是一样的). 只讲AC自动机和DP的关系(个人理解). AC自动机 又可以叫做状态机. 我一开始的认为.AC 自动机提供了一些 ...

  6. 【bzoj3530】[Sdoi2014]数数 AC自动机+数位dp

    题目描述 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3223不是幸运 ...

  7. BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)

    题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...

  8. Match:Censored!(AC自动机+DP+高精度)(POJ 1625)

     Censored! 题目大意:给定一些字符,将这些字符组成一个固定长度的字符串,但是字符串不能包含一些禁词,问你有多少种组合方式. 这是一道好题,既然出现了“一些”禁词,那么这题肯定和AC自动机有点 ...

  9. Censored! - POJ 1625(ac自动机+简单dp+高精度运算)

    题目大意:首先给一个字符集合,这个集合有N个字符,然后需要一个长度为M的句子,但是据子里面不能包含的串有P个,每个串里面的字符都是有字符集和里面的字符构成的,现在想知道最多能构造多少个不重复的句子. ...

随机推荐

  1. Python高阶函数(Map、Reduce、Filter)

    Map函数 map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回. 举例说明 比如我们有一个函数f(x)=x2,要把这个函数作用 ...

  2. Redis的五种数据结构的内部编码

    type命令实际返回的就是当前键的数据结构类型,它们分别是:string(字符串).hash(哈希). list(列表).set(集合).zset(有序集合),但这些只是Redis对外的数据结构. 实 ...

  3. 万恶之源 - Python文件操作

    文件操作 初始文件操作 使用Python来读写文件是非常简单的操作,我们使用open()函数来打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作了 根据打开方式的不同能够执行的操作 ...

  4. 【Flask】关于Flask的request属性

    前言 在进行Flask开发中,前端需要发送不同的请求及各种带参数的方式,比如GET方法在URL后面带参数和POST在BODY带参数,有时候又是POST的表单提交方式,这个时候就需要从request提取 ...

  5. turple list dict 互相转换

    1. 字典(dict) dict = {'name': 'Zara', 'age': 7, 'class': 'First'} 1.1 字典---字符串 print (type(str(dict)), ...

  6. Python 之 os.walk()

    原文地址https://www.cnblogs.com/JetpropelledSnake/p/8982495.html          http://www.runoob.com/python/o ...

  7. selenium webdriver窗口切换(上)

    selenium webdriver窗口切换,有时候在做自动化的时候需要打开很多很多的页面, 当在操作不同的页面的时候需要切换窗口,下面是如何切换到前后页面窗口的操作: package test201 ...

  8. C语言头文件、库文件的查找路径

    在 程序设计中,文件包含是很有用的.一个大的程序可以分为多个模块,由多个程序员分别编程.有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用.这样,可避免在每个 ...

  9. js五星好评2

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. jms应用

    构建jms http://blog.csdn.net/haoxingfeng/article/details/9167895