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

      

  • 相关阅读:
    TensorFlow进阶(三)---变量的创建、初始化
    TensorFlow进阶(二)---张量的操作
    TensorFlow进阶(一)----张量的阶和数据类型
    TensorFlow入门
    卷积神经网络识别手写数字实例
    解决在win系统下使用DOS命令开启TensorBoard的问题及方法步骤
    TensorFlow------单层(全连接层)实现手写数字识别训练及测试实例
    TensorFlow------TFRecords的读取实例
    TensorFlow------TFRecords的分析与存储实例
    TensorFlow------读取二进制文件实例
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4492883.html
Copyright © 2020-2023  润新知