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;

}

转载于:https://www.cnblogs.com/yejinru/archive/2012/04/30/2476968.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值