题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4339
线段树或者 树状数组+二分
记录两个字符串在该区间内有多少个字符相匹配。
线段树:
1 # include<stdio.h> 2 # include<string.h> 3 # include<stdlib.h> 4 # define N 1000005 5 char s1[N],s2[N]; 6 struct node{ 7 int l,r; 8 int num; 9 }tree[4*N]; 10 void bulid(int l,int r,int t) 11 { 12 int mid; 13 tree[t].l=l; 14 tree[t].r=r; 15 tree[t].num=0; 16 if(l==r) 17 { 18 if(s1[l]==s2[l]) tree[t].num=1; 19 return; 20 } 21 mid=(l+r)/2; 22 bulid(l,mid,2*t); 23 bulid(mid+1,r,2*t+1); 24 tree[t].num=tree[2*t].num+tree[2*t+1].num; 25 } 26 void updata1(int l,int t) 27 { 28 tree[t].num--; 29 if(tree[t].l==tree[t].r) return; 30 if(l<=tree[2*t].r) updata1(l,2*t); 31 else updata1(l,2*t+1); 32 } 33 void updata2(int l,int t) 34 { 35 tree[t].num++; 36 if(tree[t].l==tree[t].r) return; 37 if(l<=tree[2*t].r) updata2(l,2*t); 38 else updata2(l,2*t+1); 39 } 40 int query(int l,int r,int t) 41 { 42 int ans1; 43 if(tree[t].r - tree[t].l + 1 == tree[t].num) return r-l+1; 44 if(tree[t].l==tree[t].r) return tree[t].num; 45 if(r<=tree[2*t].r) return query(l,r,2*t); 46 else if(l>=tree[2*t+1].l) return query(l,r,2*t+1); 47 else 48 { 49 ans1=query(l,tree[2*t].r,2*t); 50 if(ans1==tree[2*t].r-l+1) 51 { 52 return ans1+query(tree[2*t+1].l,r,2*t+1); 53 } 54 else return ans1; 55 } 56 } 57 int main() 58 { 59 int ncase,t; 60 int l1,l2; 61 int count,ans,ss,h,Q,flag; 62 char ch; 63 scanf("%d",&ncase); 64 for(t=1;t<=ncase;t++) 65 { 66 scanf("%s",s1); 67 scanf("%s",s2); 68 l1=strlen(s1); 69 l2=strlen(s2); 70 ans=l1; 71 if(l2<ans) ans=l2; 72 bulid(0,ans-1,1); 73 scanf("%d",&Q); 74 printf("Case %d:\n",t); 75 while(Q--) 76 { 77 scanf("%d",&ss); 78 if(ss==1) 79 { 80 scanf("%d%d %c",&flag,&h,&ch); 81 if(flag==1) 82 { 83 //s1[h]=ch; 84 if(h<l2 && s1[h]==s2[h] && s1[h]!=ch) updata1(h,1); 85 else if(h<l2 && s1[h]!=s2[h] && ch==s2[h]) updata2(h,1); 86 s1[h]=ch; 87 } 88 else 89 { 90 if(h<l1 && s1[h]==s2[h] && ch!=s1[h]) updata1(h,1); 91 else if(h<l1 && s1[h]!=s2[h] && ch==s1[h]) updata2(h,1); 92 s2[h]=ch; 93 } 94 } 95 else 96 { 97 scanf("%d",&h); 98 count=query(h,ans-1,1); 99 printf("%d\n",count); 100 } 101 } 102 } 103 return 0; 104 }
树状数组+二分
1 # include<stdio.h> 2 # include<string.h> 3 # include<stdlib.h> 4 # define N 1000005 5 char s1[N],s2[N]; 6 int sum[N]; 7 void updata1(int x,int n) 8 { 9 while(x<=n) 10 { 11 sum[x]++; 12 x += (x&(-x)); 13 } 14 } 15 void updata2(int x,int n) 16 { 17 while(x<=n) 18 { 19 sum[x]--; 20 x+=(x&(-x)); 21 } 22 } 23 int query(int x) 24 { 25 int num=0; 26 while(x>=1) 27 { 28 num+=sum[x]; 29 x-=(x&(-x)); 30 } 31 return num; 32 } 33 int main() 34 { 35 int ncase,t,i; 36 int l1,l2,ans,ans1,ans2; 37 int l,r,mid; 38 int flag,num,h,Q; 39 char ch; 40 scanf("%d",&ncase); 41 for(t=1;t<=ncase;t++) 42 { 43 scanf("%s",s1+1); 44 scanf("%s",s2+1); 45 l1=strlen(s1+1); 46 l2=strlen(s2+1); 47 ans=l1; 48 if(l2<ans) ans=l2; 49 memset(sum,0,sizeof(sum)); 50 for(i=1;i<=ans;i++) 51 { 52 if(s1[i]==s2[i]) updata1(i,ans); 53 } 54 printf("Case %d:\n",t); 55 scanf("%d",&Q); 56 while(Q--) 57 { 58 scanf("%d",&flag); 59 if(flag==1) 60 { 61 scanf("%d%d %c",&num,&h,&ch); 62 h++; 63 if(num==1) 64 { 65 if(h<l2 && s1[h]!=s2[h] && ch==s2[h]) updata1(h,ans); 66 else if(h<l2 && s1[h]==s2[h] && ch!=s1[h]) updata2(h,ans); 67 s1[h]=ch; 68 } 69 else 70 { 71 if(h<l1 && s1[h]!=s2[h] && ch==s1[h]) updata1(h,ans); 72 else if(h<l1 && s1[h]==s2[h] && ch!=s2[h]) updata2(h,ans); 73 s2[h]=ch; 74 } 75 } 76 else 77 { 78 scanf("%d",&h); 79 h++; 80 l=h; 81 r=ans; 82 num=0; 83 ans1=query(h-1); 84 while(l<=r) 85 { 86 mid=(l+r)/2; 87 ans2=query(mid); 88 if(ans2-ans1==mid-h+1) 89 { 90 num=mid-h+1; 91 l=mid+1; 92 } 93 else r=mid-1; 94 } 95 printf("%d\n",num); 96 } 97 } 98 } 99 return 0; 100 }