POJ 1625 Censored!(AC自动机+高精度+dp)

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 ;
}
上一篇:haproxy配置文件详解和ACL功能


下一篇:android:自己定义组合控件Weight(高仿猫眼底部菜单条)