sdut 最长公共子序列问题
Problem Description
從一個(gè)給定的串中刪去(不一定連續(xù)地刪去)0個(gè)或0個(gè)以上的字符,剩下地字符按原來(lái)順序組成的串。例如:“ ”,“a”,“xb”,“aaa”,“bbb”,“xabb”,“xaaabbb”都是串“xaaabbb”的子串。(例子中的串不包含引號(hào)。)?
編程求N個(gè)非空串的最長(zhǎng)公共子串的長(zhǎng)度。限制:2<=N<=100;N個(gè)串中的字符只會(huì)是數(shù)字0,1,…,9或小寫英文字母a,b,…,z;每個(gè)串非空且最多含100個(gè)字符;N個(gè)串的長(zhǎng)度的乘積不會(huì)超過(guò)30000。
Input
文件第1行是一個(gè)整數(shù)T,表示測(cè)試數(shù)據(jù)的個(gè)數(shù)(1<=T<=10)。接下來(lái)有T組測(cè)試數(shù)據(jù)。各組測(cè)試數(shù)據(jù)的第1行是一個(gè)整數(shù)Ni,表示第i組數(shù)據(jù)中串的個(gè)數(shù)。各組測(cè)試數(shù)據(jù)的第2到N+1行中,每行一個(gè)串,串中不會(huì)有空格,但行首和行末可能有空格,這些空格當(dāng)然不算作串的一部分。Output
輸出T行,每行一個(gè)數(shù),第i行的數(shù)表示第i組測(cè)試數(shù)據(jù)中Ni個(gè)非空串的最長(zhǎng)公共子串的長(zhǎng)度。Example Input
1 3 ab bc cdExample Output
0
求解最長(zhǎng)公共子串問(wèn)題利用動(dòng)態(tài)規(guī)劃思想,不管是否理解動(dòng)態(tài)規(guī)劃,把這個(gè)原理弄明白就行。
首先直接給出一個(gè)例子:
主串:str[7]=”ABCBDAB”?
子串:substr[6]=”BDCABA”
求最長(zhǎng)公共子串?
我們先不考慮如何實(shí)現(xiàn)這個(gè)先來(lái)分析這個(gè)結(jié)果為多少,通過(guò)比較容易得出當(dāng)子串為BDAB時(shí)候最長(zhǎng)公共子串的值為4。
好了現(xiàn)在我們一起來(lái)分析算法了!
首先定義一個(gè)sum[][]二維數(shù)組初始化為0,行表示主串的字符,列表示子串的字符,那么sum[i][j表示主串的第i(從一開始數(shù))個(gè)字符與子串的j+1個(gè)字符的最長(zhǎng)公共子串的結(jié)果值,最后sum[7][6]的值就是最長(zhǎng)公共子串的結(jié)果。
首先主串中的A與子串匹配,當(dāng)子串?dāng)?shù)組的下標(biāo)為3、5時(shí)候匹配,首先分析3,當(dāng)下標(biāo)3與其主串的首字符匹配,那么此時(shí)sum[1][4]=1,此時(shí)的sum[1][5]=sum[1][6]=1(注意,因?yàn)槠ヅ涞竭@里的時(shí)候最長(zhǎng)公共子串仍然為1) 主串繼續(xù)匹配,str[0]=substr[5]此時(shí)sum[2][6]=1,主串往后移動(dòng),str[1]=substr[0] 則sum[2][x]=1(x>=1),,繼續(xù)移動(dòng),str[2]=str[2]此時(shí)sum[3][3]=sum[2][2]+1=2后面一以此類推...
#include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> using namespace std; int main() {char x[505],y[505];int sum[505][505],i,j,len1,len2;while(gets(x)){gets(y);len1=strlen(x);len2=strlen(y);memset(sum,0,sizeof(sum));for(i=1;i<=len1;i++){for(j=1;j<=len2;j++){if(x[i-1]==y[j-1])sum[i][j]=sum[i-1][j-1]+1;elsesum[i][j]=max(sum[i-1][j],sum[i][j-1]);}}printf("%d\n",sum[len1][len2]);}return 0; }/*超時(shí)作法 #include<iostream> #include<stdio.h> #include<algorithm> #include<cstring> using namespace std;int main() {while(1){ char str[500],substr[500];int a[500]={0},b[500]={0};gets(str);gets(substr);for(int i=0;i<strlen(substr);i++){for(int j=0;j<strlen(str);j++){if(str[j]==substr[i]){a[j]=1;//標(biāo)記 b[j]=1;}}}for(int i=1;i<strlen(str);i++){for(int j=0;j<i;j++){if(str[i]>str[j]&&(a[i])&&(a[j])&&b[i]<b[j]+1){b[i]=b[j]+1;}}} int ans=-1;for(int i=0;i<strlen(str);i++){if(ans<b[i])ans=b[i];}cout<<ans<<endl;}return 0; }*/
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的sdut 最长公共子序列问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 交叉排序
- 下一篇: C语言fwrite函数了解