zoukankan      html  css  js  c++  java
  • URAL1635——DP+回溯——Mnemonics and Palindromes

    Description

    The student Vasechkin was terribly unlucky at his oral examination. Of 42 examination questions, he didn't prepare only the last one, and he was asked exactly that question. Vasechkin was sitting in front of the professor and couldn't say anything. But the professor was in good mood and gave Vasechkin one last chance to pass the exam. He asked the poor student to name the subject in which the exam was being held. Unfortunately, Vasechkin couldn't recall the name, though he remembered that in that name there were such words as safety, programs, devices, and, possibly, informatics…
    To get ready for the reexamination, Vasechkin decided to learn the name of the subject. To better remember that long string, he decided to decompose it into palindromes and learn each of the palindromes separately. Of course, the number of palindromes in the decomposition had to be as small as possible.

    Input

    In the first line there is the name of the subject in which Vasechkin was examined. This is a nonempty line consisting of lowercase English letters. The length of the line is at most 4000 symbols.

    Output

    In the first line output the minimal number of palindromes to which the name of the subject can be decomposed. In the second line output palindromes from the optimal decomposition separated by a space. If several answers are possible, output any of them.

    Sample Input

    inputoutput
    pasoib
    
    6
    p a s o i b
    
    zzzqxx
    
    3
    zzz q xx
    
    wasitacatisaw
    
    1
    wasitacatisaw
    
     大意:找到最小的回文子串个数并输出,学到了回溯方法,因为状态转移,最后这个点更新的就是最优的情况,所以在状态转移这里设立一个path来记录当前这个状态要转移去的下标,然后只要递推就行,自己写的O(n^3)超时了  orz。不过思路很清楚
    两种方法..自己调了一下午。。。以为成功了,结果交了两发TLE+MLE两个错误0.0瞬间就惊呆了orz
    自己的
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    char  a[4200];
    int dp[4200];
    int b[4200][4200];
    int path[4200];
    int n;
    char pri[4200][4200];
    void inti(){
        for(int i = 1 ; i <= n; i++){
            for(int j = i + 1 ;j <= n; j++){
                int k,p;
                for( k = i,p = j; k < p; k++,p--){
                    if(a[k] != a[p] )
                            break;
                }
                if(k >= p)
                b[i][j] = j - i + 1;
            }
        }
        for(int i = 1 ; i <= n; i++)
            b[i][i] = 1;
    
    }
    int main()
    {
        while(~scanf("%s",a+1)){
            memset(b,0,sizeof(b));
            memset(dp,0,sizeof(dp));
            memset(path,0,sizeof(path));
         n = strlen(a+1);
        inti();
        dp[1] = 1;
        for(int i = 2 ; i <= n;i++)
            dp[i] = dp[i-1]+1;
        dp[0] = 0;
        for(int i = 1; i <= n; i++){
            for(int j = i ; j <= n; j++){
                if(dp[j-b[i][j]]+1 <= dp[j]){
                    dp[j] = dp[j-b[i][j]] + 1;
                    path[j] = j - b[i][j];
                }
            }
        }
        //for(int i = 1; i <= n ;i++)
        //printf("%d
    ",path[i]);
         // for(int i = 1; i <= n; i++)
         //   for(int j = i+1 ; j <= n;j++)
         //       printf("%d ",b[i][j]);
         //  for(int i = 1 ; i <= n; i++)
         //      printf("%d ",dp[i]);
        printf("%d
    ",dp[n]);
        int i = n ;
        int t1 = 1;
        int t2;
        memset(pri,0,sizeof(pri));
        while( i >= 1){  
             t2 = 1;
          for(int j = path[i]+1; j <= i ;j++){
              pri[t1][t2++] = a[j];
            // printf("%d%d%c ",t1,t2-1,pri[t1][t2-1]);
          }
        //  printf("
    ");
          t1++;
          i = path[i];
        }
     //   printf("%d",t1);
       for(int i = t1 - 1; i >= 1; i--){
            for(int j = 1; pri[i][j] != '';j++)
               printf("%c",pri[i][j]);
           if(i!=1) printf(" ");
        }
       printf("
    ");
        }
        return 0;
    }
    

    AC的

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int dp[4010];
    int pre[4010];
    int ok[4010][4010];
    char s[4010];
    void print(int p)
    {
        if(pre[p] == -1){
            for(int i = 0 ; i <= p ;i++){
                printf("%c",s[i]);
            }
        }
           else{
            print(pre[p]);
            printf(" ");
            for(int i = pre[p]+1; i <= p ;i++)
                printf("%c",s[i]);
        }
    }
    
    void solve()
    {
        int len = strlen(s);
        for(int i = 0;i < len ;i++){//i表示长度
            for(int j = 0 ;i+j < len;j++){
                if(i == 0) ok[j][j+i] = 1; //因为从小到大所以是符合这个方程的   
                else if(i == 1) ok[j][j+i] = (s[j] == s[j+i]);
                else if(s[j] == s[j+i])
                    ok[j][j+i] = ok[j+1][j+i-1];
            }
        }
        for(int i = 0; i < len ;i++){
            dp[i] = i + 1;
            pre[i] = i - 1;//从0到i是否回文
            if(ok[0][i]) {
                dp[i] = 1;
                pre[i] = -1;
                continue;
            }
            for(int j = i - 1; j >= 0 ; j--){
                if(ok[j+1][i]){//j表示i前面
                    if(dp[i] > dp[j] + 1){
                        dp[i] = dp[j] + 1;
                        pre[i] = j;
                    }
                }
            }
        }
        printf("%d
    ",dp[len-1]);
        print(len-1);//dfs
        printf("
    ");
    }
    
    int main()
    {
        while(~scanf("%s",s)){
            memset(dp,0,sizeof(dp));
            memset(pre,0,sizeof(pre));
            memset(ok,0,sizeof(ok));
            solve();
        }
        return 0;
    }
    

      

  • 相关阅读:
    ZINTERSTORE — Redis 命令参考
    Wombat vim colorscheme – customized Chronosbox
    我的vim colorscheme 白色之夜 博客园
    Python list of class attributes Python
    vim配色方案colorscheme设置
    colorscheme install
    Python类中的私有成员(私有函数,私有变量)
    Pebble Overview
    用python 发送邮件
    Python发送带附件的Email
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4492883.html
Copyright © 2011-2022 走看看