zoukankan      html  css  js  c++  java
  • 【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]
  • 相关阅读:
    赫尔维茨公式
    从解析几何的角度分析二次型
    Struts 1 Struts 2
    记一次服务器被入侵的调查取证
    契约式设计 契约式编程 Design by contract
    lsblk df
    Linux Find Out Last System Reboot Time and Date Command 登录安全 开关机 记录 帐号审计 历史记录命令条数
    Infrastructure for container projects.
    更新文档 版本控制 多版本并发控制
    Building Microservices: Using an API Gateway
  • 原文地址:https://www.cnblogs.com/Tunix/p/4398653.html
Copyright © 2011-2022 走看看