1002 Phone Numbers 字符串dp

/*

 

字符串DP,但是要找到用最小的字符串来匹配,所以用dp储存当前所使用过的字符串数。

打印路径的话直接用数组表示前缀

 

*/

#include <iostream>

#include <string>

#include <cstring>

#include <cstdio>

using namespace std;

string s = "22233344115566070778889990";

#define X 50010

int dp[X],pre[X],len[X],p[X],L;

string a[X],in[X],b;

void change(int x)

{

       len[x] = in[x].size();

       for(int i=0;i<len[x];i++)

              a[x].push_back(s[in[x][i]-'a']);

}

bool check(int i,int j) //判断是否匹配

{

       for(int k=len[j]-1;k>=0;k--)

              if(b[i-1]==a[j][k])

                     i--;

              else

                     return false;

       return true;

}

void print(int x)   //递归打印路径

{

       if(p[x]>0)

       {

              print(p[x]);

              cout<<" ";

       }

       cout<<in[pre[x]];

}

int main()

{

       freopen("sum.in","r",stdin);

       freopen("sum.out","w",stdout);

       int n;

       while(cin>>b,b[0]!='-')

       {

              cin>>n;

              for(int i=0;i<n;i++)

              {

                     cin>>in[i];

                     change(i);

              }

              memset(pre,-1,sizeof(pre));

              memset(p,-1,sizeof(p));

              L = b.size();

              memset(dp,-1,sizeof(dp));

              dp[0] = 0;

              for(int i=1;i<=L;i++)

              {

                     for(int j=0;j<n;j++)

                            if(len[j]<=i&&b[i-1]==a[j][len[j]-1]&&check(i,j))

                            {

                                   if(dp[i-len[j]]==-1)    //若前面不能匹配的话

                                          continue;

                                   int x;

                                   if(dp[i]==-1)   //当前还没有其他的字符串匹配

                                          x = dp[i-len[j]]+1;

                                   else        //当前已经有其他字符串,取最小的那个

                                          x = min(dp[i],dp[i-len[j]]+1);

                                   if(dp[i]!=x)    //若当前的还没匹配或者当前的比以前匹配过的所用字符串数目少,更新

                                   {

                                          dp[i] = dp[i-len[j]]+1;

                                          pre[i] = j;

                                          p[i] = i-len[j];

                                   }

                            }

              }

              if(dp[L]<0)

                     cout<<"No solution."<<endl;

              else

              {

                     print(L);

                     cout<<endl;

              }

       }

       return 0;

}

posted @ 2012-04-30 16:01  yejinru  阅读(204)  评论(0编辑  收藏  举报