BZOJ2099: [Usaco2010 Dec]Letter 恐吓信
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2099: [Usaco2010 Dec]Letter 恐吓信相关的知识,希望对你有一定的参考价值。
给两个长度不超过50000的串,A串可每次截连续一段复制出来,求最少复制几次能得到B串。
方法一:SAM。不会。
方法二:其实就是拿B去A上面匹配若干次。多次匹配的话可以把A先建个后缀数组,然后每次二分到B的位置搞匹配。匹配一次怕太慢的话,用hash吧!二分匹配长度找到第一个不可匹配的位置,就可以算匹配长度啦!
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m; 9 #define maxn 50011 10 char t[maxn],p[maxn],c; 11 int ht[maxn],hp[maxn]; 12 int sa[maxn],cnt[maxn],rank[maxn],y[maxn]; 13 void makesa(char* s) 14 { 15 int n=strlen(s),m=26; 16 for (int i=0;i<m;i++) cnt[i]=0; 17 for (int i=0;i<n;i++) cnt[rank[i]=s[i]-‘A‘]++; 18 for (int i=1;i<m;i++) cnt[i]+=cnt[i-1]; 19 for (int i=n-1;i>=0;i--) sa[--cnt[rank[i]]]=i; 20 for (int k=1;k<=n;k<<=1) 21 { 22 int p=0; 23 for (int i=n-k;i<n;i++) y[p++]=i; 24 for (int i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; 25 for (int i=0;i<m;i++) cnt[i]=0; 26 for (int i=0;i<n;i++) cnt[rank[y[i]]]++; 27 for (int i=1;i<m;i++) cnt[i]+=cnt[i-1]; 28 for (int i=n-1;i>=0;i--) sa[--cnt[rank[y[i]]]]=y[i]; 29 memcpy(y,rank,sizeof(y)); 30 p=0;rank[sa[0]]=0; 31 for (int i=1;i<n;i++) 32 rank[sa[i]]=y[sa[i]]==y[sa[i-1]] && ((sa[i]+k>=n && sa[i-1]+k>=n) 33 || (sa[i]+k<n && sa[i-1]+k<n && y[sa[i]+k]==y[sa[i-1]+k]))?p:++p; 34 if (p==n-1) break; 35 m=p+1; 36 } 37 } 38 void makeh(char* s,int* h) 39 { 40 int n=strlen(s); 41 h[0]=s[0]-‘A‘; 42 for (int i=1;i<n;i++) 43 h[i]=h[i-1]*27+s[i]-‘A‘; 44 } 45 int pw[maxn]; 46 void makepw(int n) 47 { 48 pw[0]=1; 49 for (int i=1;i<=n;i++) 50 pw[i]=pw[i-1]*27; 51 } 52 bool ok(int x,int y) 53 { 54 int L=0,R=min(n-x,m-y); 55 while (L<R) 56 { 57 if (ht[x+mid-1]-ht[x-1]*pw[mid]==hp[y+mid-1]-hp[y-1]*pw[mid]) L=mid; 58 else R=mid-1; 59 } 60 return p[y+L]<=t[x+L]; 61 } 62 int lcp(int x,int y) 63 { 64 int now=0; 65 while (x<n && y<m && t[x]==p[y]) now++,x++,y++; 66 return now; 67 } 68 void play(int &x) 69 { 70 int L=0,R=n; 71 while (L<R) 72 { 73 int mid=(L+R)>>1; 74 if (ok(sa[mid],x)) R=mid; 75 else L=mid+1; 76 } 77 if (!L) x+=lcp(sa[L],x); 78 else if (L<n) x+=max(lcp(sa[L-1],x),lcp(sa[L],x)); 79 else x+=lcp(sa[n-1],x); 80 } 81 bool isalpha(char c) {return c>=‘A‘ && c<=‘Z‘;} 82 int main() 83 { 84 scanf("%d%d",&n,&m); 85 t[n]=‘\0‘;p[m]=‘\0‘; 86 for (int i=0;i<n;i++) 87 { 88 while (!isalpha(c=getchar())); 89 t[i]=c; 90 } 91 for (int i=0;i<m;i++) 92 { 93 while (!isalpha(c=getchar())); 94 p[i]=c; 95 } 96 makesa(t); 97 makeh(t,ht);makeh(p,hp);makepw(max(n,m)); 98 int now=0,ans=0; 99 while (now<m) play(now),ans++; 100 printf("%d\n",ans); 101 return 0; 102 }
以上是关于BZOJ2099: [Usaco2010 Dec]Letter 恐吓信的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ——2101: [Usaco2010 Dec]Treasure Chest 藏宝箱
BZOJ 2100: [Usaco2010 Dec]Apple Delivery
bzoj 2100: [Usaco2010 Dec]Apple Deliveryspfa