HDU 4300 Clairewd’s message
这题比赛时,题意看了N久才看懂,囧。。。
算法又错了两次:
错误算法:
1. 用二分找密文长度。。
2.用只求了一次next函数找最长前缀匹配后缀,忽略了其可能有交集,在这题中是不允许的。。
正确算法:
饶了这么多弯,终于回到正道了,求一次KMP就可以解决。
用截获的文本后半段做主串,用前半段做模式串。
用KMP求出其最长匹配主串的长度。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #include<stdlib.h> char str[101000]; char st[101000]; char temp1[101000]; char temp2[101000]; char hash[101000]; int next[101000]; void get_next( ) { int len = strlen( st + 1); int i = 1, j = 0; next[1] = 0; while( i < len ) { if( st[i] == st[j] || j == 0 ) { ++i,++j; next[i] = j; } else j = next[j]; } } //记录最多能匹配的字符个数 int kmp(char *A, char *B) { int len1 = strlen(A + 1); int len2 = strlen(B + 1); int i = 1, j = 1; while( i <= len1 && j <= len2 ) { if( A[i] == B[j] || j == 0 ) { if( i == len1 ) return j; ++i, ++j; } else { j = next[j]; } } return 0; } void HASH( ) { int len = strlen( str + 1); int num = 0; for( int i = 1; i <= len; i++) { hash[str[i]-'a'] = 'a' + num++; } } int main( ) { int N; scanf("%d",&N); while( N-- ) { scanf("%s%s",str+1,st+1); HASH( ); memset(next, 0, sizeof(next)); get_next( ); int len = strlen(st+1); for( int i = 1; i <= len /2 + 1; i++) temp1[i] = hash[st[i]-'a']; temp1[len+1]='\0'; /* int n = 1; if( len == 1 ) { printf("%c%c\n",st[1], hash[st[1]-'a']); continue; } for( int i = (len+1)/2; i <= len; i++) temp2[n++] = st[i]; temp2[n] = '\0'; */ strcpy(temp2 + 1, st + (len + 1 ) / 2 + 1); int n = kmp(temp2, temp1); printf("%s",st + 1); for( int i = n + 1; i <= len - n; i++) { printf("%c",hash[st[i]-'a']); } puts(""); } return 0; }
posted on 2012-07-20 22:22 more think, more gains 阅读(179) 评论(0) 编辑 收藏 举报