最小线段覆盖 C神奇项链

母亲节就要到了,小 H 准备送给她一个特殊的项链。
这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色。

为了制作这个项链,小 H 购买了两个机器。
第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:
   假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或 abaca。

现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。

 

 

最小线段覆盖 ... 

我想的是树状数组 区间差分修改 ... 

没有Hack 自己 ai...

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rel(i,x,y) for(ll i=(x);i<(y);i++)
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define red(i,x,y) for(ll i=(x);i>=(y);i--)
#define res(i,x) for(ll i=head[x];i;i=nxt[i])
using namespace std;

const ll N=1e5+5;
const ll Inf=1e18;

inline ll read() {
    ll x=0;char ch=getchar();bool f=0;
    while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?-x:x;
}
int R[120000];
char s[120000],S[120000];
struct node
{

    int x,y;

}a[120000];
int cnt=0;
int n;
int tot;
void init()
{
     tot=1;
    S[0]='@';
    S[1]='#';
    for(int i=1;i<=n;i++)
{
    S[++tot]=s[i];
    S[++tot]='#';
}
    S[++tot]='\0';

}
void mlc()
{

    int p=0;
    int maxlen=0;
    for(int i=1;i<tot;i++)
    {
        if(i<maxlen) R[i]=min(R[2*p-i],maxlen-i+1);
        else
        R[i]=1;
        while(S[i+R[i]]==S[i-R[i]]) R[i]++;
    
        {        
            a[++cnt].x=i-R[i]+1;
            a[cnt].y=i+R[i]-1;
        }
            if(i+R[i]-1>maxlen)
        {
                maxlen=i+R[i]-1;
                p=i;
        
        }
    }        
}

bool cmp(node aa,node b)
{
    if(aa.x==b.x)
    return aa.y>b.y;
    else
    return aa.x<b.x;

}
int main() {

    while(scanf("%s",s+1)!=EOF)
{
    
    for(int i=0;i<=n;i++)
{
    R[i]=0;

}
    n=strlen(s+1);
    cnt=0;
    int ans=0;
    init();
    mlc();
    sort(a+1,a+1+cnt,cmp);
    int l=a[1].y;
    int now=l;
    int j;
    int fla=0;int tes=0;
    if(a[1].y>=a[cnt].y) 
    {
        cout<<0;
        continue;

    }
    for(int i=2;i<=cnt;i++)
    {
        l=now;
        
            while(a[i].x<=l&&i<=cnt)
{
            
            now=max(now,a[i].y);i++;

}
    i--;
    if(now==l) break;
    else ans++;



}    cout<<ans<<endl;

}
}

 

posted @ 2019-08-14 09:19  ALEZ  阅读(264)  评论(0编辑  收藏  举报