lightOJ 1420 Subsequences forming Strings(拼字符串)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1420
题意:给出三个字符串A、B、C。拿出A和B的一些subsequences组成C。问有多少种方式?

思路:显然,我们可以用f[i][j][k]表示用A的前i个和B的前j个拼出C的前k个的方案数。对于C的每个位置k,我们要在A或B中找到一个与 C[k]相同的,若A[i]=C[k]则DFS(i+1,j,k+1),若B[j]=C[k]则DFS(i,j+1,k+1)。但是我们发现,比如 A[i]=C[k],其实i位置之后还是有与C[k]相等的,那些位置也是需要计算的,比如A的下一个位置i1,那么应该 DFS(i1+1,j,k+1)。但是下一次计算DFS(i1+1,j,k+1)的时候我们又不能用B[j]来更新。因为,若下次使用B[j]这次也是用 B[j],虽然两次的i是不同的,但是还是有可能出现重复计算的情况。为了解决这个问题,我们再在状态的记录上增加一维,f[i][j][k][3],0 表示只能用A来得到 C[k],1表示只能用B来得到C[k],2表示都可以。这样当前若A[i]=C[k],那么下一步就可以使DFS(i+1,j,k+1,2)或者 (DFS,i+1,j,k,0)。

 

int f[N][N][N][3],visit[N][N][N][3];

char a[N],b[N],c[N];

int n,m,K;

int w;





void up(int &x,int y)

{

    x+=y;

    if(x>mod) x-=mod;

}







int DFS(int x,int y,int z,int flag)

{

    if(z==K+1) return 1;

    if(visit[x][y][z][flag]==w) return f[x][y][z][flag];





    visit[x][y][z][flag]=w;

    int ans=0,i;

    if(flag!=1)

    {

        for(i=x;i<=n;i++) if(a[i]==c[z])

        {

            up(ans,DFS(i+1,y,z+1,2));

            up(ans,DFS(i+1,y,z,0));

            break;

        }

    }

    if(flag!=0)

    {

        for(i=y;i<=m;i++) if(b[i]==c[z])

        {

            up(ans,DFS(x,i+1,z+1,2));

            up(ans,DFS(x,i+1,z,1));

            break;

        }

    }





    return f[x][y][z][flag]=ans;

}



int main()

{

    int num=0;

    rush()

    {

        RD(a+1); RD(b+1); RD(c+1);

        n=strlen(a+1);

        m=strlen(b+1);

        K=strlen(c+1);

        w++;

        printf("Case %d: ",++num);

        PR(DFS(1,1,1,2));

    }

}

 

 

 

你可能感兴趣的:(sequence)