  /**//*
      题意:对于DFA,F(u,c)表示u在输入c后跳到状态F(u,c)
             该DFA有K个状态,给出起点S,还有T个终点和状态转移函数F(u,c)
             问S到T路径长度为N的路径条数        
             不过F(u,c)有些特殊,如果边G[u,c]=1表示从u转到F(u,c)后,
             接下来要用的字母还是c,不是下一个字母
  
             对于普通的DFA,求从起点到终点的路径条数可以用DP
             dp[n,pos]表示长度为n,从起点到pos的路径条数
             dp[n,pos]+=dp[n-1,pos'] , pos'->pos
             初始dp[0,1]=1
             
             先用dfs处理掉那些特殊边,然后就是普通的DFA了
             在某点沿某条边出发,如果有G(u,c)=1的环,说明永远不会accept,
             否则我们就将这条边指向第一个G(u,c)=0处(E[pos][ch]=dfs(E[pos][ch]))
  */
  #include<cstdio>
  #include<cstring>
  
  typedef long long LL;
  const int ml=100,base=100000000,nd=8;
  int n,m,k,i,j;
   struct bign { int len,s[ml]; };
   void print(bign &bi) {
      printf("%d",bi.s[bi.len]);
      for(int i=bi.len-1;i;i--)printf("%08d",bi.s[i]);
  }
   void fixlen(bign &bi) { while(bi.len>1 && !bi.s[bi.len])bi.len--; }
   void init(bign &bi) { bi.len=1; memset(bi.s,0,sizeof(bi.s)); }
   void init(bign &bi,int a) {
      init(bi);
       while(a) { bi.s[bi.len++]=a%base; a/=base; }
      bi.len--;
  }
   int cmp(bign &a,bign &b) {
      if( a.len != b.len ) return a.len-b.len;
      for(int i=a.len;i;i--)if(a.s[i] != b.s[i]) return a.s[i]-b.s[i];
      return 0;
  }
   bign operator+(bign &a,bign &b) {
      bign c; int i; init(c);
       for(i=1;i<=a.len || i<=b.len || c.s[i];i++) {
          c.s[i]+=a.s[i]+b.s[i];
          c.s[i+1]=c.s[i]/base; c.s[i]%=base;
      }
      if(i>1)c.len=i-1;else c.len=1;
      return c;
  }
  
  bool G[1001][27];
  int F[1001][27],E[1001][27];//F原来的  E新建的
  int Ta[1001];
  int K,N,Z,S,TNum;
  bign dp[2][1001],ZERO;
  
   /**//*dfs是抄的 */
  int dfs(int pos,int ch)//check char  for all pos     -1 for cycle , 0 for not check
    {
      if(E[pos][ch]!=-1)
        {
          if(!G[pos][ch])//ok
              E[pos][ch]=F[pos][ch];
          else
            {
              E[pos][ch]=-1;
              E[pos][ch]=dfs(F[pos][ch],ch);//
          }
      }
      return E[pos][ch];
  }
  
  int main()
    {
  //    freopen("in","r",stdin);
      init(ZERO);
      int T;
      scanf("%d",&T);
      while(T--)
        {
          char str[30];
          scanf("%s",str);Z=strlen(str);
          scanf("%d%d%d",&K,&S,&TNum);
          for(int i=0;i<TNum;i++)scanf("%d",&Ta[i]);
          for(int i=1;i<=K;i++)
              for(int j=1;j<=Z;j++)
                  scanf("%d",&F[i][j]);
          memset(E,0,sizeof(E));//新边,0表示还未定
          for(int i=1;i<=K;i++)
              for(int j=1;j<=Z;j++)
                  scanf("%d",&G[i][j]);
          for(int j=1;j<=Z;j++)        
              for(int i=1;i<=K;i++)
                  if(!E[i][j])dfs(i,j);
          scanf("%d",&N);
          for(int i=1;i<=K;i++)init(dp[0][i]);
          init(dp[0][S],1);//S not 1
          for(int n=1;n<=N;n++)
            {
              for(int i=1;i<=K;i++)init(dp[n&1][i]);
              for(int i=1;i<=K;i++)
                {
                  if(cmp(dp[(n-1)&1][i],ZERO)==0)continue;
                  for(int j=1;j<=Z;j++)
                      if(E[i][j]>0)dp[n&1][E[i][j]]=dp[n&1][E[i][j]]+dp[(n-1)&1][i];
              }
          }
          bign ans;
          init(ans);
          for(int i=0;i<TNum;i++)
              ans=ans+dp[N&1][Ta[i]];
          print(ans);
          puts("");
          if(T)puts("");
      }
      return 0;
  } 
		 
		
	 
	  
	 
	
	    
    
 
				
			  | 
		 
		 
	 | 
	
		
		
			
			
			
				
			
常用链接
		随笔分类
		
				
			
	
		Links
		
				
			
	
搜索
最新评论
	 
			
			 
			
			 | 
		 
		 
	 |