zoukankan      html  css  js  c++  java
  • bzoj1090[SCOI2003]字符串折叠

    bzoj1090[SCOI2003]字符串折叠

    题意:

    折叠的定义如下:1. 一个字符串可以看成它自身的折叠。记作S。2. X(S)是X(X>1)个S连接在一起的串的折叠。记作X(S)。注意括号可以嵌套。给出字符串,求折叠后字符串的最短长度。

    字符串长度≤100。

    题解:

    区间dp。f[i][j]=min(f[i][k]+f[k+1][j],f[i][k]+len(getnum(i,k,i,j)))。f[i][j]表示i到j的最短折叠长度。getnum(i,k,i,j)表示字符串[i..k]在字符串[i..j]中出现了几次(如果后者不是前者重复组成的返回正无穷),这个可以用哈希求。len表示一个数的长度,注意正无穷的长度为正无穷。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 110
     6 #define ll unsigned long long
     7 #define zsye 2333
     8 #define INF 0x3fffffff
     9 using namespace std;
    10 
    11 int f[maxn][maxn],n; ll hash[maxn],mi[maxn];
    12 char str[maxn];
    13 ll get(int l,int r){
    14     return hash[r]-hash[l-1]*mi[r-l+1];
    15 }
    16 int getnum(int l1,int r1,int l2,int r2){
    17     if((r2-l2+1)%(r1-l1+1)!=0)return INF; ll orzzs=get(l1,r1);
    18     inc(i,1,(r2-l2+1)/(r1-l1+1))if(orzzs!=get(l2+(i-1)*(r1-l1+1),l2+i*(r1-l1+1)-1))return INF;
    19     return (r2-l2+1)/(r1-l1+1);
    20 }
    21 int numlen(int x){if(x==INF)return INF; int tot=0; while(x)x/=10,tot++; return tot;}
    22 void dfs(int l,int r){
    23     if(f[l][r]!=-1)return; inc(i,l,r-1)dfs(l,i),dfs(i+1,r); f[l][r]=INF;
    24     inc(i,l,r-1)f[l][r]=min(f[l][r],f[l][i]+f[i+1][r]);
    25     inc(i,l,r)f[l][r]=min(f[l][r],f[l][i]+2+numlen(getnum(l,i,l,r)));
    26 }
    27 int main(){
    28     scanf("%s",str+1); n=strlen(str+1); mi[0]=1;
    29     inc(i,1,n)hash[i]=hash[i-1]*zsye+str[i],mi[i]=mi[i-1]*zsye;
    30     memset(f,-1,sizeof(f)); inc(i,1,n)f[i][i]=1;
    31     dfs(1,n); printf("%d",f[1][n]); return 0;
    32 }

    20161110

  • 相关阅读:
    mybatis 控制器注解介绍(一)
    maven(基础介绍一)
    mybatis 动态sql语句(3)
    mybatis 动态sql语句(2)
    MyBatis 工具 pndao
    mybatis~动态SQL(1)
    模拟102
    模拟99
    模拟95
    模拟94
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/6055390.html
Copyright © 2011-2022 走看看