zoukankan      html  css  js  c++  java
  • 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;

    }

  • 相关阅读:
    oo第八次作业--5,6,7次作业总结
    OO前三次作业总结
    软工总结
    黄衫感想博客
    软工结对编程博客
    软工第一次阅读
    软工第0次作业
    OO第四次博客
    OO第三次博客
    OO第二次博客
  • 原文地址:https://www.cnblogs.com/yejinru/p/2476968.html
Copyright © 2011-2022 走看看