/**//* 题意:对于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
搜索
最新评论
|
|