poj 1625
poj 1625 题意: 这张trie图和普通的trie树不同之处在于,它补全了所有trie树中原本不存在的边。每一个状态节点的某一个子节点若不存在,则将其指向这个状态节点的fail节点所对应的那个相同的子节点。即 若 ch[r][c]==0,ch[r][c]=ch[f[r]][c](大白书的写法) 这样一来原来的trie树变成了一张有向的状态转移图。从trie图中的根节点开始,沿着有向边走m步,即可得到一个长度为m的字串。 需要注意的有两点: 下面帖代码: #include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define maxnode 105
#define sigma_size 52
using namespace std;
const int base = 10;
int n,m,p;
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
int f[maxnode];
int last[maxnode];
char charset[maxnode];
char ban[12];
int get(char a)
{
for(int i = 0; i < n; i++)
if(charset[i] == a)
return i;
return -1;
}
void initial()
{
memset(ch[0],0,sizeof(ch[0]));
sz = 1;
}
void insert(char *s)
{
int l = strlen(s);
int u = 0;
for(int i = 0; i < l; i++)
{
int c = get(s[i]);
if(!ch[u][c])
{
memset(ch[sz],sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] = 1;
}
void getfail()
{
queue<int >q;
f[0] = 0;
for(int c = 0; c < n; c++)
{
int u = ch[0][c];
if(u)
{
f[u] = 0;
q.push(u);
last[u] = 0;
}
}
while(!q.empty())
{
int r = q.front();
q.pop();
for(int c = 0; c < n; c++)
{
int u = ch[r][c];
if(!u)
{
ch[r][c] = ch[f[r]][c];
continue;
}
q.push(u);
int v = f[r];
while(v && !ch[v][c])
v = f[v];
f[u] = ch[v][c];
last[u] = val[f[u]] ? f[u] : last[f[u]];
// if(last[u])
// val[u] = 1;
}
}
}
struct BigInt
{
int v[maxnode],len;
BigInt(int r = 0)
{
memset(v,sizeof(v));
for(len = 0; r > 0; r /= base)v[len++] = r % base;
}
BigInt operator + (const BigInt &a)
{
BigInt ans;
int i,c = 0;
for(i = 0; i < len || i < a.len || c > 0; i++)
{
if(i < len)c += v[i];
if(i < a.len)c += a.v[i];
ans.v[i] = c % base;
c /= base;
}
ans.len = i;
return ans;
}
void print()
{
printf("%d",len == 0 ? 0 : v[len - 1]);
for(int i = len - 2; i >= 0; i--)
printf("%d",v[i]);
printf("n");
}
};
BigInt dp[52][maxnode];
int check(int k,int j)
{
int ans = 0;
for(int i = 0; i < n; i++)
if(ch[k][i] == j)
ans++;
return ans;
}
int main()
{
initial();
scanf("%d%d%d",&n,&m,&p);
scanf("%s",charset);
while(p--)
{
scanf("%s",ban);
insert(ban);
}
getfail();
//初始化边界条件
for(int i = 0; i <= m; i++)
for(int j = 0; j < sz; j++)
{
dp[i][j] = BigInt();
}
dp[0][0] = BigInt(1);
//dp过程
for(int i = 1 ; i <= m; i++)
{
for(int j = 0; j < sz; j++)
{
if(val[j] || val[last[j]])
continue;
for(int k = 0; k < sz; k++)
{
if(val[last[k]] || val[k])
continue;
int ti=check(k,j);
for(int c=0;c<ti;c++)
dp[i][j] = dp[i][j] + dp[i - 1][k];
}
}
}
BigInt ans = BigInt();
for(int i = 0; i < sz; i++)
{
ans = ans + dp[m][i];
}
ans.print();
return 0;
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |