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

原创 2012年03月30日 16:59:28

       题目是要说小于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;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

POJ 3233 - Matrix Power Series(等比矩阵求和)

题意:矩阵求和 思路:用二分幂解决,和等比数列求和的二分方法一样 等比数列求和法(摘自http://blog.csdn.net/acdreamers/article/details/7851144 A...
  • kalilili
  • kalilili
  • 2015年04月07日 22:28
  • 985

等比矩阵求和超简法及其python代码10行实现

等比矩阵求和:S = A + A2 + A3 + … + Ak 经典的 二分法、构造法,这里就不介绍了,在CSDN里很容易找到,这里介绍一个超级简单的计算方法: S  = A ...
  • Qi_Python
  • Qi_Python
  • 2017年12月04日 20:40
  • 97

等比、等差数列求和(递归)

等比 #include void main() { int a,q,n; puts("请输入首项:"); scanf("%d",&a); puts("请输入公比:"...
  • grave2015
  • grave2015
  • 2015年09月20日 08:41
  • 1096

矩阵经典题目三:poj 3233 Matrix Power Series(等比矩阵求和)

http://poj.org/problem?id=3233 ps转: 用二分方法求等比数列前n项和:即   原理:   (1)若n==0   (2)若n%2==0     ...
  • u013081425
  • u013081425
  • 2014年06月12日 17:13
  • 1215

Hdu 2243 考研路茫茫——单词情结 (AC自动机+矩阵)

哎哟喂,中文题。。。不说题意了。 首先做过POJ 2778可以知道AC自动机是可以求出长度为L的串中不含病毒串的数量的。 POJ 2778的大概思路就是先用所有给的病毒串建一个AC自动机,...
  • u010709592
  • u010709592
  • 2014年10月04日 16:35
  • 1021

Jacobi迭代与SOR迭代求解希尔伯特矩阵

给出线性方程组 Hn*x = b,其中系数矩阵Hn为希尔伯特矩阵:      假设 x ∗ =(1, 1, . . . , 1)T,b = Hnx ∗。若取 n = 6,8, 10,分别用 Jaco...
  • qqlu_did
  • qqlu_did
  • 2015年04月27日 01:10
  • 2109

【math】梯度(gradient)、雅克比矩阵(Jacobian)、海森矩阵(Hessian)

梯度: f(x)在各个方向上的偏导,组成的向量
  • DSbatigol
  • DSbatigol
  • 2013年10月10日 16:30
  • 12169

[HDOJ 2243] 考研路茫茫——单词情结 [AC自动机+动态规划+矩阵加速]

给至多6个字符串,每个长度不
  • jinzhao1994
  • jinzhao1994
  • 2014年08月01日 10:06
  • 501

hdoj 2243 考研路茫茫——单词情结 【AC自动机 + 构造矩阵】

考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota...
  • chenzhenyu123456
  • chenzhenyu123456
  • 2015年10月11日 15:49
  • 246

HDOJ 2243 考研路茫茫——单词情结 AC自动机+矩阵快速求幂和

考研路茫茫——单词情结#include #include #include #include using namespace std; int n,l,sz; int ch[40][26],f...
  • u010270082
  • u010270082
  • 2014年07月02日 13:19
  • 468
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDOJ-2243 AC自动机.等比矩阵求和
举报原因:
原因补充:

(最多只允许输入30个字)