[BZOJ3790]神奇项链

本文介绍了一道关于构造特殊项链的算法题目。通过将问题转化为区间覆盖问题,并采用贪心算法进行解决。代码实现了Manacher算法寻找最长回文子串,并通过区间合并策略最小化机器使用次数。

Description

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

Input

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

Output

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

Sample Input

abcdcba
abacada
abcdef

Sample Output

0
2
5

HINT

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

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

Source

 

还是很容易想到搞成区间覆盖问题的,然后贪心一下就行了

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define M 100010
 6 using namespace std;
 7 int n,N,ans,now,r,mx;
 8 int len[M],p[M]; 
 9 char a[M],s[M*2];
10 void change()
11 {
12     s[0]='&';
13     for(int i=0;i<N;i++)
14     {
15         s[++n]='#';
16         s[++n]=a[i];
17     }
18     s[++n]='#';
19 }
20 void manacher()
21 {
22     int maxright=0,mid;
23     for(int i=1;i<=n;i++)
24     {
25         if(i<maxright) len[i]=min(len[mid*2-i],maxright-i);
26         else len[i]=1;
27         while(s[i-len[i]]==s[i+len[i]]) len[i]++;
28         if(len[i]+i>maxright)
29         {
30             maxright=len[i]+i;
31             mid=i;
32         }
33     }
34 }
35 struct point{
36     int l,r;
37 }b[M];
38 bool cmp(point a1,point a2) {return a1.l<a2.l||(a1.l==a2.l&&a1.r>a2.r);}
39 int main()
40 {
41     while(scanf("%s",a)!=EOF)
42     {
43         N=strlen(a);
44         n=0;
45         int cnt=0;
46         change();
47         manacher();
48         for(int i=1;i<=n;i++) b[++cnt].l=i-len[i]+1,b[cnt].r=i+len[i]-1;
49         sort(b+1,b+1+cnt,cmp);
50         r=b[1].r;ans=1;now=2;
51         while(r<n)
52         {
53             mx=r;
54             while(now<=cnt&&b[now].l<=r)
55             {
56                 mx=max(mx,b[now].r);
57                 now++;
58             }
59             ++ans;r=mx;
60         }
61         printf("%d\n",ans-1);
62     }
63     return 0;
64 }

 

转载于:https://www.cnblogs.com/Slrslr/p/9498923.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值