【BZOJ】【3790】神奇项链
Manacher算法/DP
找出所有的回文串,看做是一个个线段,那么问题就转化成了用最少的线段将整个区间覆盖起来,可以重叠,那么这就是一个DP了= =
Orz ZKY大爷,让蒟蒻开眼界了……头一次知道原来树状数组还可以反过来用0.0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n",ans-1); 77 } 78 return 0; 79 }
3790: 神奇项链
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 126 Solved: 63
[Submit][Status][Discuss]
Description
母亲节就要到了,小 H 准备送给她一个特殊的项链。这个项链可以看作一个用小写字
母组成的字符串,每个小写字母表示一种颜色。为了制作这个项链,小 H
购买了两个机器。第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和
一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠。例如:aba和aca连接起来,可以生成串abaaca或
abaca。现在给出目标项链的样式,询问你需要使用第二个机器多少次才能生成这个特殊的项链。
Input
输入数据有多行,每行一个字符串,表示目标项链的样式。
Output
多行,每行一个答案表示最少需要使用第二个机器的次数。
Sample Input
abcdcba
abacada
abcdef
abacada
abcdef
Sample Output
0
2
5
2
5
HINT
每个测试数据,输入不超过 5行
每行的字符串长度小于等于 50000