zoukankan      html  css  js  c++  java
  • URAL

    题意:

    演队在口试中非常不幸。在42道考题中,他恰好没有准备最后一道题,而刚好被问到的正是那道题。演队坐在教授面前,一句话也说不出来。但教授心情很好,给了演队最后一次通过考试的机会。他让这个可怜的学生说出考试要考的科目。不幸的是,演队想不起这个科目名字,尽管他记得科目里有诸如安全、程序、设备、可能还有信息学……

    为了准备复试,演队决定记住这门课的名字。为了更好地记住那根长字符串,他决定把它分解成回文,并分别学习每个回文。当然,分解过程中的回文数必须尽可能少。

    Input

    输入一行字符串表示为这门课的名字。这是由小写英文字母组成的非空行。这一行的长度最多是4000个字符。

    Output

     第一行输出可以分解科目名称的最小的回文字符串数目。在第二行输出回文所有的回文字符串,由空格分隔。如果有几个答案是可能的,输出其中任何一个。

    Input

    pasoib

    Output

    6
    p a s o i b

    Input

    zzzqxx

    Output

    3
    zzz q xx

    Input

    wasitacatisaw

    Output

    1
    wasitacatisaw

    题解:

    可以对每一个区间[l,r]用哈希赋一个唯一的值,对区间[l,r]正序哈希一个值,逆序哈希一个值。那么如果区间[l,r]是回文串,那么这个区间的正序哈希值应该等于逆序哈希值

    dp[i]=min(dp[j-1]+1,dp[i]),dp[i]代表从1-i区间的回文序列数量

    这个状态转移方程就是当区间[j,i]是回文串的时候

    如果不会哈希,也可以用一个二维数组来记录一下区间[l,r]是不是回文串,判断回文串就用while循环(这种方法见代码2)

    代码1:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<vector>
     7 #include<map>
     8 #define mem(a,x) memset(a,x,sizeof(a))
     9 using namespace std;
    10 const int INF=0x3f3f3f3f;
    11 const int maxn=4005;
    12 const int mod=1000000009;
    13 const int base=13333;
    14 typedef long long ll;
    15 ll dp[maxn];//从1--i中回文串的最少个数
    16 ll h1[maxn],h2[maxn],p[maxn],n;
    17 ll pre[maxn];
    18 char s[maxn];
    19 string str[maxn];
    20 //找出来[l,r]这个区间正序的哈希值
    21 ll get1(ll l,ll r)
    22 {
    23     return h1[r]-h1[l-1]*p[r-l+1];
    24 }
    25 //找出来[l,r]这个区间倒序的哈希值
    26 ll get2(ll l,ll r)
    27 {
    28     return h2[r]-h2[l-1]*p[r-l+1];
    29 }
    30 //如果区间[l,r]的正序逆序哈希值一样,那么这个区间就是回文串
    31 bool check(ll i,ll j)
    32 {
    33     if(get1(i,j)==get2(n-j+1,n-i+1))
    34         return true;
    35     return false;
    36 }
    37 int main()
    38 {
    39     ios::sync_with_stdio(false);
    40     cin.tie(0);
    41     memset(dp,INF,sizeof dp);
    42     dp[0]=0;
    43     cin>>(s+1);
    44     n=strlen(s+1);
    45     p[0]=1;
    46     for(ll i=1; i<=n; i++)
    47     {
    48         h1[i]=h1[i-1]*base-s[i]-'a'+1;
    49         h2[i]=h2[i-1]*base-s[n+1-i]-'a'+1;
    50         p[i]=p[i-1]*base;
    51     }
    52     for(ll i=1; i<=n; i++)
    53     {
    54         for(ll j=1; j<=i; j++)
    55         {
    56             if(check(j,i))
    57             {
    58                 if(dp[i]>(dp[j-1]+1))
    59                 {
    60                     pre[i]=j;  //记录路径
    61                     dp[i]=dp[j-1]+1;
    62                 }
    63             }
    64         }
    65     }
    66     cout<<dp[n]<<endl;
    67     int id=0;
    68     int now=n;
    69     while(now)
    70     {
    71         for(int i=pre[now]; i<=now; i++)
    72             str[id]+=s[i];  //str串记录回文串
    73         now=pre[now]-1;
    74         id++;
    75     }
    76     for(int i=id-1; i>=0; i--)
    77     {
    78         if(i!=0)
    79             cout<<str[i]<<' ';
    80         else
    81             cout<<str[i]<<endl;
    82     }
    83 }
    View Code

    代码2:(参考:https://blog.csdn.net/zmx354/article/details/20078995)

      1 #include <iostream>
      2 
      3 #include <algorithm>
      4 
      5 #include <cstdlib>
      6 
      7 #include <cstdio>
      8 
      9 #include <cstring>
     10 
     11 #include <queue>
     12 
     13 #include <cmath>
     14 
     15 #include <stack>
     16 
     17  
     18 
     19 #pragma comment(linker, "/STACK:1024000000");
     20 
     21 #define LL long long int
     22 
     23 #define ULL unsigned long long int
     24 
     25 #define _LL __int64
     26 
     27 #define INF 0x3f3f3f3f
     28 
     29 #define Mod 1000000009
     30 
     31  
     32 
     33 using namespace std;
     34 
     35  
     36 
     37 char s[4010];
     38 
     39  
     40 
     41 bool dp[4001][4001];
     42 
     43  
     44 
     45 int ans[4010];
     46 
     47  
     48 
     49 int di[4010];
     50 
     51  
     52 
     53 void Output(int l)
     54 
     55 {
     56 
     57     if(l == 0)
     58 
     59         return ;
     60 
     61  
     62 
     63     Output(di[l]);
     64 
     65  
     66 
     67     if(di[l] != 0)
     68 
     69         printf(" ");
     70 
     71  
     72 
     73     for(int i = di[l]+1;i <= l; ++i)
     74 
     75     {
     76 
     77         printf("%c",s[i]);
     78 
     79     }
     80 
     81 }
     82 
     83  
     84 
     85 int main()
     86 
     87 {
     88 
     89     int l,i,j,h,e;
     90 
     91  
     92 
     93     scanf("%s",s+1);
     94 
     95  
     96 
     97     l = strlen(s+1);
     98 
     99  
    100 
    101     memset(dp,false,sizeof(dp));
    102 
    103  
    104 
    105     for(i = 1;i <= l; ++i)
    106 
    107     {
    108 
    109         dp[i][i] = true;
    110 
    111         h = i-1;
    112 
    113         e = i+1;
    114 
    115  
    116 
    117         while(1 <= h && e <= l && s[h] == s[e])
    118 
    119         {
    120 
    121             dp[h][e] = true;
    122 
    123             h--,e++;
    124 
    125         }
    126 
    127  
    128 
    129         h = i,e = i+1;
    130 
    131  
    132 
    133         while(1 <= h && e <= l && s[h] == s[e])
    134 
    135         {
    136 
    137             dp[h][e] = true;
    138 
    139             h--,e++;
    140 
    141         }
    142 
    143     }
    144 
    145  
    146 
    147     memset(ans,INF,sizeof(ans));
    148 
    149  
    150 
    151     ans[0] = 0;
    152 
    153  
    154 
    155     di[1] = 0;
    156 
    157  
    158 
    159     for(i = 1;i <= l; ++i)
    160 
    161     {
    162 
    163         for(j = i;j >= 1; --j)
    164 
    165         {
    166 
    167             if(dp[j][i])
    168 
    169             {
    170 
    171                 if(ans[i] > ans[j-1]+1)
    172 
    173                 {
    174 
    175                     ans[i] = ans[j-1]+1;
    176 
    177                     di[i] = j-1;
    178 
    179                 }
    180 
    181             }
    182 
    183         }
    184 
    185     }
    186 
    187  
    188 
    189     printf("%d
    ",ans[l]);
    190 
    191  
    192 
    193     Output(l);
    194 
    195  
    196 
    197     puts("");
    198 
    199  
    200 
    201     return 0;
    202 
    203 }
    View Code
  • 相关阅读:
    MvcApplication 中方法的那点事
    Html 中阻止事件冒泡的三种方法比较
    WPF中 ItemsSource 和DataContext不同点
    解决:Visual Studio 启动就报错退出
    webapi是如何绑定参数的(How WebAPI does Parameter Binding)
    %cd% 和%~dp0%的区别及cd跨盘符切换路径问题
    win10中matlabR2015b安装libsvm
    MATLAB2015b链接MinGW编译器
    网易内推编程题:异或运算求混合颜料的最小种类
    小易喜欢的单词
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12653725.html
Copyright © 2011-2022 走看看