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;
    }
    

      

  • 相关阅读:
    事物的五种配置方式(转载)
    Spring入门
    leetcode刷题3
    LeetCode刷题2
    LeetCode刷题1
    bootstraptable使用总结之前端样式设计
    初识Handsontable
    Java之file类
    OpenCV学习系列教程第五篇:测试和提高代码的效率
    OpenCV学习系列教程第四篇:图像的算术操作
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4492883.html
Copyright © 2011-2022 走看看