1. 程式人生 > >華為 oj 公共子串計算

華為 oj 公共子串計算

水題,原來以為用dp陣列  結果wrong了兩次 我想還是自己小題大做了···呵呵··

獻給初學者作為參考

#include <stdio.h>
#include <string.h>
#define MAX 200


int getCommonStrLength(char * pFirstStr, char * pSecondStr)
{
	int m = strlen(pFirstStr);
	int n = strlen(pSecondStr);
	int max = 0;
	int number = 0;
	if(pFirstStr==NULL||pSecondStr==NULL)
	{	
		return 0;
	}
		
	for( int i = 0;i < m;i ++)
	{
		for(int j = 0;j < n;j ++)
		{
			if(i==m||j==n){break;}
			while(pFirstStr[i] == pSecondStr[j])
			{	
				i++;
				j++;
				number++;		
			}		
			if(max < number)
			{
				max = number;
			}
			if(i==m||j==n){break;}
		}
		
	}
	return max;
}



int main(void)
{
	char s1[200] = {
		"\0"
	};
	
	char s2[200]= {
		"\0"
	};

	scanf("%s",s1);
	scanf("%s",s2);
	
	
	int num = getCommonStrLength(s1,s2);
	
	printf("%d\n",num);
	
	
	return 0;
}


==========================================

最長公共子串是常見的面試題

出現困惑的是讀者對 

最長公共子串 

最長公共子序列產生混淆

二者的區別是 

最長公共子串 要求子串中的單個字元必須都是連續的

最長公共子序列  要求 去掉一部分元素  只要滿足 序列中部分的元素 符合某種規律即可 

他們處理辦法的核心都是一致的

----------------------------------引用自某大神參加面試的總結

子序列跟子串的求法類似,都是使用動態規劃的思想,

s1每次增加一個字元,看與s2當前位置的字元是不是相同,如果相同做相應的處理,如果不同,做另外的處理。

子序列的處理方式:

相同的情況下,該二維陣列的位置等於[i-1][j-1]+1

不同的情況下,該二維陣列的位置等於MAX(d[i-1][j],d[i][j-1])

下面描述下子串的求法。

最長公共子串,要求字元是連續的。那麼在[s1每次增加一個字元,看與s2當前位置的字元是不是相同]

相同的情況下,二維陣列的位置等於[i-1][j-1]+1,

不同的情況下,二維陣列的位置等於0,最後再檢視二維陣列的資訊即可得到最長公共子串的長度,同時可以回溯二維陣列得到最長公共字串的內容。


----------------------------------------------------------------------------------------------

上面是正確的演算法 錯誤的演算法我也粘貼出來僅供參考

核心

動態規劃

dp【i】【j】 表示  串1 從開始字元到 第i個字元 ,串2從開始字元到第j個字元 ,兩個串中最常公共子串的個數

滿足如下

1.當s1[i] = s2[j]  dp[i][j] = d[i-1][j-1]+1(公共子串滿足連續的性質)

2.不等時   dp[i][j] = 0(我不是很理解!求指教,,!!!!!!!!)

#include <stdio.h>

#include <string.h>

#define MAX 200
int dp[MAX][MAX]={
}; 

int getCommonStrLength(char * pFirstStr, char * pSecondStr)
{
	int m = strlen(pFirstStr);
	int n = strlen(pSecondStr);
	int max = 0;
		
	for( int i = 0;i < m;i ++)
	{
		for(int j = 0;j < n;j ++)
		{
			if(pFirstStr[i] == pSecondStr[j])
			{
				if(i ==0 || j == 0)
				{	
					dp[i][j] = 1;
				}
				else
				{
					dp[i][j] = dp[i-1][j-1] + 1;
				}			
			}
			
			if(max < dp[i][j])
			{
				max = dp[i][j];
			}
		}
		
	}
	return max;
}



int main(void)
{
	char s1[200] = {
		"\0"
	};
	
	char s2[200]= {
		"\0"
	};
	
	memset(dp+2,0,MAX);

	scanf("%s",s1);
	scanf("%s",s2);
	
	
	int num = getCommonStrLength(s1,s2);
	
	printf("%d\n",num);
	
	
	return 0;
}
------------------------------ps

後最陣列也可實現

kmp演算法  也就是字串查詢演算法 只要是基於後最陣列的都可以實現  (怪不得覺得很眼熟。但是kmp演算法卻一時想不起來  我哭····)

--------------------------------------------------------------

演算法學習還是蠻辛苦的 ,求各位大神指教,給出建議,小弟十分感激