Sicily 4697. Common Subsequence

来源:互联网 发布:沈阳网络营销黑马网络 编辑:程序博客网 时间:2024/06/09 22:17

软件学院2011级C语言机考热身题,就是软件学院2010级C语言机考题(我做到第3题才意识到这就是我当年考试的题目,当时10题AC了7题,排名是20左右?这个热身题系列拿了当年的前8题,这道题就是我当时做不出的第8题)。
现在回想起来,那10道题哪里是给刚学C语言的人考的?如果是大学前没接触过C语言之类编程语言的人,不掌握一定的技巧和知识根本AC不了5道题(就是那时候起,我才发现我编程还算不错……)貌似当年是2道题及格,记不太清楚了。
言归正传,这道题好像属于动态规划的范畴(意见保留,因为我现在还不知道动态规划是什么东西。如果是的话,那当年就是叫新生去做一道动态规划的题……)。相关方程是:
sub[ i ][ j ] = max( 0 or 1 + sub[ i + 1 ][ k + 1 ], sub[ i + 1 ][ j ] )
意思是,从字符串X的i位置和字符串Y的j位置开始,最大的公共子序列长度是:
1.若Y的j位置及以后无法与X的i位置匹配,这里取值为0;否则,将匹配位置记为k,这里取值为sub[ i + 1 ][ k + 1 ];
2.这里取值为sub[ i + 1 ][ j ];
以上两者较大的就是从字符串X的i位置和字符串Y的j位置开始的最大的公共子序列长度。直观上的感觉可以理解为:若在字符串Y中无法找到与当前字符串X的位置元素相匹配的,显然不存在公共子序列,所以所求为0。若能够找到相匹配的,就要考虑要不要匹配(因为若匹配了,匹配位置前面的字符串就不能再匹配了,有可能得不偿失),若选择匹配,那么X和Y的位置都向下移动一位,继续进行匹配;若选择不匹配,就将X的位置移向下一位,继续进行匹配。由于我们需要的是最长公共子序列,所以两种选择都要执行,然后取较大者。 我们所求明显是sub[ 0 ][ 0 ],这个过程依据上面的方式进行即可,可以用递归的形式实现,也可以用状态转移方程求出,前者递归层次为n,后者时间复杂度为O(n3),两个半斤八两,时间相差不大,就看个人喜好了。

Run Time: 0.02sec

Run Memory: 304KB

Code length: 842Bytes

Submit Time: 2012-01-07 14:19:34

// Problem#: 4697// Submission#: 1179222// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/// All Copyright reserved by Informatic Lab of Sun Yat-sen University#include <cstdio>#include <cstring>using namespace std;int main(){    int N;    int i, j, k;    int Xlen, Ylen;    int t1, t2;    int sub[ 15 ][ 15 ];    char X[ 14 ], Y[ 14 ];    scanf( "%d", &N );    while ( N-- ) {        scanf( "%s%s", X, Y );        Xlen = strlen( X );        Ylen = strlen( Y );        memset( sub, 0, sizeof( sub ) );        for ( i = Xlen - 1; i >= 0; i-- ) {            for ( j = Ylen - 1; j >= 0; j-- ) {                for ( k = j; k < Ylen; k++ ) {                    if ( X[ i ] == Y[ k ] )                        break;                }                t1 = ( k == Ylen ? 0: 1 + sub[ i + 1 ][ k + 1 ] );                t2 = sub[ i + 1 ][ j ];                sub[ i ][ j ] = ( t1 > t2 ? t1: t2 );            }        }        printf( "%d\n", sub[ 0 ][ 0 ] );    }    return 0;}                                 


 

原创粉丝点击