最小线段覆盖 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; } }
刀剑映出了战士的心。而我的心,漆黑且残破