sicily 1037. Decorations

/*

题意: 给出一些长度相同的子串,目标串必须是由这些子串首尾连接起来,问有多少长度为L的目标串满足,比如:
4 5 6
ABB BCA BCD CAB CDD DDA
则目标串有两个: BCABB 和 BCDDA
定义连接 ch[i]->ch[j] , 只要满足 ch[i][1..len-1] = ch[j][0..len-2],即串i的后部分与串j的前部分重叠
把每个输入的字符串当作顶点,字符串之间若可以连接则建立一条边,由此得到初始图,
问题就转化成求 顶点数为 L-len+1 的路径 的总数

*/


#include<iostream> //DP
#include<cstring>

using namespace std;
int n,L,m,len,side[602][602],dp[602][602];
//dp[i][j]表示由 i 个字符串组成 ,结尾的字符串为 ch[j] 的组合有多少种可能
char ch[602][12];

int main()
{
int i,j,k;
while(cin>>n>>L>>m,n) // 表示有 n 种字符,目标串的长度是L,有 m 个组合子串
{

for(i=0;i<m;++i)
cin>>ch[i];
len=strlen(ch[0]);
memset(side,0,sizeof(side));
for(i=0;i<m;++i) //建图
for(j=0;j<m;++j)

{
int link=1;
for(k=1;k<len;++k)
if(ch[i][k]!=ch[j][k-1])
{
link=0;
break;
}
if(link)
{
side[i][j]=1; //表示ch[i]能与ch[j]首尾相连,比如 CAB->ABB
}

}
memset(dp,0,sizeof(dp));
for(j=0;j<m;++j)
dp[1][j]=1; //由1个字符串组成,那就是ch[j]本身
for(i=2;i<=L-len+1;++i)

for(j=0;j<m;++j)
{
for(k=0;k<m;++k)
if(side[k][j])
dp[i][j]+=dp[i-1][k];
//dp[i][j]表示由 i 个字符串组成 ,结尾的字符串为 ch[j] 的组合有多少种可能
}

int ans=0;
for(j=0;j<m;++j)
ans+=dp[L-len+1][j]; //由L-len+1个字符串首尾连接起来
cout<<ans<<endl;

}
return 0;
}

posted on 2011-07-05 12:20  sysu_mjc  阅读(213)  评论(0编辑  收藏  举报

导航