算法:
比赛时没有想到好的算法,暴力是O( Q * N )肯定超时。
赛后,线段树,树状数组,HASH都能AC,想了下,的确用树状数组
时间复杂度就可以优化到O(Q * lgN * lgN)
2000msAC.。。
View Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<algorithm> using namespace std; #define MAXN 2000100 char str1[MAXN],str2[MAXN],str[10]; int dx[MAXN]; int N, lenmax, lenmin;int lowbit( int x ) { return x&-x; }void add( int x, int val, int M) {while( x <= M ){dx[x] += val;x += lowbit(x);} }int sum( int x ) {int num = 0;while( x > 0 ){num += dx[x];x -= lowbit( x ); } return num; }void pre( ) {int i = 1;int len1 = strlen(str1+1), len2 = strlen(str2+1);lenmin = len1 < len2 ? len1 : len2;while( i <= len1 ){if( str1[i] == str2[i] ){add(i, 1, lenmin); } i++; } }bool jugde(int start, int x) {int x1 = sum(start+x-1) - sum(start-1);if( x1 == x )return true;return false; }int find( int l, int r, int start) {int ans = 0;while( l <= r ){int mid = (l + r)/2;if( jugde(start,mid) ){ans = mid;l = mid + 1; }else r = mid - 1; }return ans; }int main( ) {int T, a, b, c, ans = 1;scanf("%d",&T);while( T-- ){scanf("%s%s",str1+1,str2+1); scanf("%d",&N);memset(dx,0,sizeof(dx));pre( );printf("Case %d:\n",ans++);for( int i = 1; i <= N; i++){scanf("%d",&a);if( a == 2 ){scanf("%d",&b);b++;printf("%d\n",find(0,lenmin,b));}else{ scanf("%d%d%s",&b,&c,str);c++; if( str1[c] == str2[c] && str[0] != str1[c] ){add(c,-1,lenmin);if( b == 1 )str1[c] = str[0];elsestr2[c] = str[0];}else if( str1[c] != str2[c] ){if( b == 1 ){if( str2[c] == str[0] ){add(c,1,lenmin); str1[c] = str[0]; }elsestr1[c] = str[0]; }else if( b == 2 ){if( str1[c] == str[0] ){add(c,1,lenmin); str2[c] = str[0]; } elsestr2[c] = str[0]; } } }} }return 0; }
HASH,要用到差值取模,时间复杂度为O( Q * lgN),写了一两个小时,还在调试中。。代码能力弱啊。。。
明天继续搞。。
郁闷啊。。从下到上的最大长度写了N久没写出,自己感觉真的不好写,从上到下真的很好写,利用回溯,写起来真的方便,自己。。
一直被标程的从下到上困扰,真的二,忘记了还可以从上到下。thanks 旭。。
View Code
#pragma comment(linker, "/STACK:16777216") #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<math.h> #include<map> #include<set> #include<algorithm> using namespace std; #define MAXN 1000010 #define Prime 29 #define LL long long struct node {int left, right;LL w1,w2; }seg[MAXN<<4]; char str1[MAXN], str2[MAXN], str[10]; LL P[MAXN]; int num[MAXN], nmax;void pre( ) {P[0] = 1;for( int i = 1; i <= 1000005; i++)P[i] = P[i-1] * Prime; }void build( int l, int r, int root ) {int mid = (l + r) / 2;seg[root].left = l;seg[root].right = r;if( l == r ){seg[root].w1 = str1[l];seg[root].w2 = str2[l];num[l] = root;return; }build(l, mid, root * 2 );build(mid+1,r,root * 2 + 1);seg[root].w1 = seg[root << 1].w1 + seg[(root<<1)+1].w1 * P[( seg[root<<1].right - seg[root<<1].left + 1)];seg[root].w2 = seg[root << 1].w2 + seg[(root<<1)+1].w2 * P[( seg[root<<1].right - seg[root<<1].left + 1)]; }void Modify( int root, int x, char c, int f) {int mid = (seg[root].left + seg[root].right) / 2;int l = seg[root].left;int r = seg[root].right;if( l == x && r == x ){if( f == 1 )seg[root].w1 = c ;elseseg[root].w2 = c ;return;}if( x > mid )Modify( (root << 1) + 1, x, c, f);elseModify( root << 1, x, c, f);if( f == 1 )seg[root].w1 = seg[root << 1].w1 + seg[(root<<1)+1].w1 * P[( seg[root<<1].right - seg[root<<1].left + 1)];elseseg[root].w2 = seg[root << 1].w2 + seg[(root<<1)+1].w2 * P[( seg[root<<1].right - seg[root<<1].left + 1)]; }int find( int p) {if( seg[p].w1 == seg[p].w2 ){return seg[p].right - seg[p].left + 1; }else if( seg[p].left != seg[p].right ){int ret = find( p << 1);if( ret == seg[p<<1].right - seg[p<<1].left + 1 ){ret += find( (p << 1) + 1); }return ret; }elsereturn 0; }int sum( int p, int x) {if( seg[p].left == seg[p].right ){if( seg[p].w1 == seg[p].w2 ){return 1; } elsereturn 0; } else{int mid = (seg[p].left + seg[p].right) / 2, ret;if( x <= mid ){ret = sum( p << 1, x );if( ret == seg[p<<1].right - x + 1 ) //左子树满的 {ret += find((p << 1) + 1);} } else{ret = sum( (p << 1) + 1, x ); }return ret; } }int main( ) {int N,T, a, b, c, abc = 1;scanf("%d",&T);pre( );while( T-- ){scanf("%s%s",str1,str2);scanf("%d",&N);int len1 = strlen(str1);int len2 = strlen(str2);nmax = len1 < len2 ? len1 : len2;build(0,nmax-1,1);printf("Case %d:\n",abc++);for( int i = 1; i <= N; i++){scanf("%d",&a);if( a == 2 ){scanf("%d",&b);if( b >= nmax ){puts("0");continue; }printf("%d\n",sum(1,b)); }else{scanf("%d%d%s",&b,&c,str);if( c >= nmax ){// puts("0");continue;}Modify(1,c,str[0], b);}}}return 0; }