学堂 学堂 学堂公众号手机端

HDOJ-2243AC自动机.等比矩阵求和

lewis 1年前 (2024-04-22) 阅读数 11 #技术


题目是要说小于L长度的由小写字母组成的字符串有多少个包含所给的串...

从正方向想..要求出包含的..并且还要踢去重复包含的..又要加上被多踢的..整个一容斥问题了...但这题明显是不可行的...那么换个角度..先求出总共小于L的单词数(26^1+26^2+26^3+...26^L)..然后再减去不包括所给字符串的单词...相当于把每个单词看成POJ2778中的病毒...


但还有个问题...如何求出矩阵A的 A+A^2+A^3+....A^L .. 这里参考了​​http://www.cppblog.com/baby-fly/archive/2009/08/18/93686.html​​所构造的矩阵...

等比矩阵求和,有经典算法,假定原矩阵为A,阶数为n,那么构造一个阶数为2n的矩阵,如下
| A E | 其中O代表O矩阵,E代表单位矩阵,这样,求出的K次矩阵的右上n子矩阵正好是
| O E | 等比矩阵的K项和,这种构造法比我实现的两次二分快了4倍左右。

这里有个错误要注意...求出K次矩阵的右上子矩阵应该是K-1项的和...


Program:

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<queue>
#define ull unsigned __int64
using namespace std;
struct node1
{
int son[26],fail;
bool word;
}point[205];
struct node
{
ull s[65][65];
}temp,h,_2M[35],T;
char s[7];
queue<int> myqueue;
ull ans;
int n,l,m;
void Built_Trie()
{
int i,len,h;
memset(point[0].son,0,sizeof(point[0].son));
point[0].word=point[0].fail=0;
m=0;
while (n--)
{
scanf("%s",s);
len=strlen(s);
h=0;
for (i=0;i<len;i++)
{
if (!point[h].son[s[i]-'a'])
{
m++;
point[h].son[s[i]-'a']=m;
memset(point[m].son,0,sizeof(point[m].son));
point[m].word=point[m].fail=0;
}
h=point[h].son[s[i]-'a'];
if (point[h].word) break;
}
point[h].word=true;
}
return;
}
void Built_AC_Automation()
{
int i,h,k;
while (!myqueue.empty()) myqueue.pop();
for (i=0;i<26;i++)
if (point[0].son[i]) myqueue.push(point[0].son[i]);
while (!myqueue.empty())
{
h=myqueue.front();
myqueue.pop();
for (i=0;i<26;i++)
if (point[h].son[i])
{
k=point[h].fail;
while (k && !point[k].son[i]) k=point[k].fail;
point[point[h].son[i]].fail=point[k].son[i];
if (point[point[k].son[i]].word)
point[point[h].son[i]].word=true;
myqueue.push(point[h].son[i]);
}
}
return;
}
void Output_Matrix(node h)
{
int i,j;
for (i=1;i<=2*m;i++)
{
for (j=1;j<=2*m;j++) printf("%3I64u",h.s[i][j]);
printf("\n");
}
}
void Built_Matrix()
{
int i,j,k;
memset(h.s,0,sizeof(h.s));
for (i=0;i<=m;i++)
if (!point[i].word)
for (j=0;j<26;j++)
{
k=i;
while (k && !point[k].son[j]) k=point[k].fail;
if (!point[point[k].son[j]].word)
h.s[i+1][point[k].son[j]+1]++;
}
m++;
j=1;
for (i=1;i<=m;i++)
{
h.s[j][i+m]=h.s[j+m][i+m]=1;
j++;
}
return;
}
node Matrix_Mul(node a,node b,int m)
{
int i,j,k;
memset(temp.s,0,sizeof(temp.s));
for (k=1;k<=2*m;k++)
for (i=1;i<=2*m;i++)
for (j=1;j<=2*m;j++)
temp.s[i][j]+=a.s[i][k]*b.s[k][j];
return temp;
}
void getmatrix(node h,int m,int l)
{
int p=0,i;
l++;
ull k;
_2M[0]=h;
k=1;
for (i=1;i<=30;i++)
{
_2M[i]=Matrix_Mul(_2M[i-1],_2M[i-1],m);
k*=2;
p++;
if (k>=l) break;
}
memset(T.s,0,sizeof(T.s));
for (i=1;i<=2*m;i++) T.s[i][i]=1;
while (l)
{
while (k>l)
{
k/=2;
p--;
}
T=Matrix_Mul(T,_2M[p],m);
l-=k;
}
return;
}
void _26P(int l)
{
node h;
ans=0;
h.s[1][1]=26; h.s[1][2]=1; h.s[2][1]=0; h.s[2][2]=1;
getmatrix(h,2,l);
ans=T.s[1][2];
}
void getdata()
{
_26P(l);
getmatrix(h,m,l);
for (int i=m+1;i<=2*m;i++) ans-=T.s[1][i];
return;
}
int main()
{
while (~scanf("%d%d",&n,&l))
{
Built_Trie();
Built_AC_Automation();
Built_Matrix();
getdata();
printf("%I64u\n",ans);
}
return 0;
}



版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门