山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3790 神奇项链(Manacher,DP+BIT | 贪心)

 

【题意】

 

    你可以产生一个回文串,也可以将两个串合并成一个串,问产生目标串需要的最少合并次数。

 

【思路】

 

  显然我们要先产生目标串中包含的极大回文字符串。

    Manacher求出每个位置可以向两边延伸的最长回文串。

    则题目转化为有若干条线段,求最少的线段将[1..n]覆盖。贪心DP皆可上,DP需要BIT优化一下。

 

【代码】

 

 1 #include<set>
 2 #include<cmath>
 3 #include<queue>
 4 #include<vector>
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<algorithm>
 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
11 using namespace std;
12 
13 typedef long long ll;
14 const int N = 2e5+10;
15 const int inf = 1e9;
16 
17 struct Node
18 {
19     int l,r;
20     bool operator < (const Node& rhs) const
21     {
22         return r<rhs.r;
23     }
24 } q[N];
25 int tot;
26 
27 char s[N],a[N];
28 int n,m,p[N];
29 
30 int C[N];
31 void upd(int x,int v)
32 {
33     for(int i=x;i;i-=i&(-i)) 
34         C[i]=min(C[i],v);
35 }
36 int query(int x)
37 {
38     if(x==0) return 0;
39     int res=inf;
40     for(int i=x;i<=n;i+=i&(-i))
41         res=min(res,C[i]);
42     return res;
43 }
44 
45 void Add(int l,int r)
46 {
47     l=l/2+1,r=r/2-1;
48     if(l>r) return ;
49     q[++tot]=(Node){l,r};
50 }
51 void Manacher()
52 {
53     m=2*n+1;
54     for(int i=1;i<=n;i++) 
55     {
56         a[i<<1]=s[i];
57         a[i<<1|1]='#';
58     }
59     a[0]='+',a[m+1]='-',a[1]='#';
60     int mx=0,id;
61     for(int i=1;i<=m;i++)
62     {
63         if(mx>i) p[i]=min(mx-i,p[id*2-i]);
64         else p[i]=1;
65         while(a[i-p[i]]==a[i+p[i]]) p[i]++;
66         Add(i-p[i],i+p[i]);
67         if(p[i]+i>mx) mx=i+p[i],id=i;
68     }
69 }
70 
71 int dp()
72 {
73     int ans=inf;
74     sort(q+1,q+tot+1);
75     FOR(i,1,tot)
76     {
77         int x=query(q[i].l-1)+1;
78         upd(q[i].r,x);
79         if(q[i].r==n) ans=min(ans,x);
80     }
81     return ans;
82 }
83 
84 int main()
85 {
86     while(scanf("%s",s+1)==1) 
87     {
88         memset(p,0,sizeof(p));
89         tot=0;
90         n=strlen(s+1);
91         FOR(i,1,n) C[i]=inf;
92         Manacher();
93         printf("%d\n",dp()-1);
94     }
95     return 0;
96 }

 

posted on 2016-04-03 09:29  hahalidaxin  阅读(462)  评论(0编辑  收藏  举报