Ural 1635. Mnemonics and Palindromes

1635. Mnemonics and Palindromes

Time limit: 1.0 second
Memory limit: 64 MB
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.

Samples

input output
pasoib
6
p a s o i b
zzzqxx
3
zzz q xx
wasitacatisaw
1
wasitacatisaw
Problem Author: Igor Chevdar
Problem Source: XIII Open USU Championship
Difficulty: 220    Printable version    Submit solution    Discussion (35)
题意:

给一个字符串,求最少可以分为多少个回文子串

代码:

#include 
   
   
    
    
#include 
    
    
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include 
                
                  #include 
                 
                   #include 
                  
                    #include 
                   
                     #include 
                    
                      #define pi acos(-1.0) #define maxn (4000 + 50) #define mol 1000000009 #define inf 0x3f3f3f3f #define Lowbit(x) (x & (-x)) using namespace std; typedef long long int LLI; //dp[i]表示从0到i最少有多少回文子串,初始为最大值 //dp[i] = min(dp[j] + 1); //pre[i]存的是以i结尾的回文子串的首地址(下标) char str[maxn]; int dp[maxn]; int vis[maxn][maxn]; int pre[maxn]; void handle(int n) { //vis[i][j]表示从i到j是不是回文串 //依据原理:如果i到j不是回文的,那么i-1到j+1也不是回文的 for(int i = 0; i < n; i ++) { for(int j = 0;; j ++) {//这是以i为对称轴,左右分别延伸j长度的 if(i - j < 0) break; if(i + j >= n) break; if(str[i + j] != str[i - j]) break; vis[i - j][i + j] = true; } for(int j = 1;; j ++) {//这是以i和i+1中间为对称轴 if(i - j + 1 < 0) break; if(i + j >= n) break; if(str[i - j + 1] != str[i + j]) break; vis[i - j + 1][i + j] = true; } } } stack 
                      
                      
                        > asta; int main() { // freopen("in.txt", "r" , stdin); // freopen("out.txt", "w" , stdout); scanf("%s",str); int len = strlen(str); fill(dp,dp + maxn,inf); fill(pre,pre + maxn,-1); memset(vis,false,sizeof(vis)); handle(len); dp[0] = 1; for(int i = 0; i < len; i ++) { if(vis[0][i]) dp[i] = 1,pre[i] = 0; } for(int i = 0;i < len;i ++){ if(dp[i] == 1) continue; for(int j = 0;j < i;j ++){ if(vis[j + 1][i] && dp[i] > dp[j] + 1){ dp[i] = dp[j] + 1; pre[i] = j + 1; } } } printf("%d\n",dp[len - 1]); int p = pre[len - 1],e = len - 1; while(e != -1 && p != -1){ asta.push(pair 
                       
                         (p,e)); e = p - 1; p = pre[e]; } while(!asta.empty()){ int x = asta.top().first; int y = asta.top().second; asta.pop(); for(int i = x;i <= y;i ++){ printf("%c",str[i]); } if(!asta.empty()) printf(" "); } return 0; } 
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
   
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值