• 【BZOJ】【3790】神奇项链


    Manacher算法/DP


      找出所有的回文串,看做是一个个线段,那么问题就转化成了用最少的线段将整个区间覆盖起来,可以重叠,那么这就是一个DP了= =

      Orz ZKY大爷,让蒟蒻开眼界了……头一次知道原来树状数组还可以反过来用0.0

     1 /**************************************************************
     2     Problem: 3790
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:176 ms
     7     Memory:3716 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 3790
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 #define mk make_pair
    22 #define fi first
    23 #define se second
    24 using namespace std;
    25 typedef long long LL;
    26 typedef pair<int,int> pii;
    27 inline int getint(){
    28     int r=1,v=0; char ch=getchar();
    29     for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1;
    30     for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0';
    31     return r*v;
    32 }
    33 const int N=1e5+10,INF=~0u>>2;
    34 /*******************template********************/
    35 char s[N];
    36 int a[N],p[N],f[N],d[N],n,m,size=0;
    37 pii seg[N];
    38 void get_seg(int l,int r){
    39     if(l>r)return;
    40     seg[++size]=mk(l,r);
    41 }
    42 bool cmp(pii a,pii b){
    43     return a.se==b.se ? a.fi<b.fi : a.se<b.se;
    44 }
    45 void update(int x,int v){
    46     for(;x;x-=x&-x) d[x]=min(d[x],v);
    47 }
    48 int query(int x){
    49     int r=d[x];
    50     for(;x && x<=size;x+=x&-x) r=min(d[x],r);
    51     return r;
    52 }
    53 int main(){
    54     while(scanf("%s",s)!=EOF){
    55         memset(d,0x7f,sizeof d); d[0]=0;
    56         memset(a,0,sizeof a);
    57         memset(f,0,sizeof f);
    58         m=n=strlen(s);
    59         F(i,1,n) a[i<<1]=s[i-1];
    60         n=n<<1|1; size=0;
    61         int id=0,mx=0;
    62         F(i,1,n){
    63             if(mx>i) p[i]=min(p[2*id-i],mx-i);
    64             else p[i]=0;
    65             while(i-p[i]-1>0 && i+p[i]+1<=n && a[i-p[i]-1]==a[i+p[i]+1])p[i]++;
    66             get_seg((i-p[i]+1)/2,(i+p[i]-1)/2);
    67             if (p[i]+i>mx) mx=p[i]+i,id=i;
    68         }
    69         sort(seg+1,seg+size+1,cmp);
    70         int ans=INF;
    71         F(i,1,size){
    72             f[i]=query(seg[i].fi-1)+1;
    73             if (seg[i].se==m) ans=min(ans,f[i]);
    74             update(seg[i].se,f[i]);
    75         }
    76         printf("%d
    ",ans-1);
    77     }
    78     return 0;
    79 }
    View Code

    3790: 神奇项链

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 126  Solved: 63
    [Submit][Status][Discuss]

    Description

    母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
    母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H 购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和 一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。 

    Input

    输入数据有多行,每行一个字符串,表示目标项链的样式。 

    Output

    多行,每行一个答案表示最少需要使用第二个机器的次数。 

    Sample Input

    abcdcba
    abacada
    abcdef

    Sample Output

    0
    2
    5

    HINT

    每个测试数据,输入不超过 5行 

    每行的字符串长度小于等于 50000 

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    3.23.谷歌中国搜索关闭的日子
    在Fedora下成功将Vim打造成适用于C/C++的IDE
    有关内存DC和双缓冲位图的问题汇总
    [转]阶乘 n! 末尾 0 的个数
    [转]各种排序算法
    [转]使用CEGUI的Editbox进行中文输入
    [转]ASP.NET中文件上传下载方法集合
    背包问题的c++解法
    [转]经典C/C++算法
    [转]编写自己的MSN机器人
  • 原文地址:https://www.cnblogs.com/Tunix/p/4398653.html
Copyright © 2020-2023  润新知