【信息学竞赛真题! ! !】信息学竞赛人必看的「USACO2009」Barn Echoes题解(C++版)

文章目录

  • A.题目描述
  • B.初步分析
  • C.提高组拓展解法

A.题目描述

题目描述

奶牛们非常享受在牛栏中牟叫,因为她们可以听到她们牟声的回音。虽然有时候并不能完全听到完整的回音。Bessie曾经是一个出色的秘书,所以她精确地纪录了所有的牟叫声及其回声。她很好奇到底两个声音的重复部份有多长。 输入两个字符串(长度为1到80个字母),表示两个牟叫声。你要确定最长的重复部分的长度。两个字符串的重复部份指的是同时是一个字符串的前缀和另一个字符串的后缀的字符串。 我们通过一个例子来理解题目。考虑下面的两个牟声:moyooyoxyzooo 和 yzoooqyasdfljkamo 第一个串的最后的部份" yzooo" 跟第二个串的第一部份重复。第二个串的最后的份" mo" 跟第一个串的第一部份重复。所以"yzooo" 跟" mo" 都是这2个串的重复部分。其中," yzooo" 比较长,所以最长的重复部份的长度就是5。

输入

两行,每一行是1个字符串表示奶牛的牟声或它的回声。

输出

一行,包含一个单独的整数表示输入的2个字符串中,一个字符串的前缀和另一个字符串的后 缀的最长的重复部份的长度。

样例输入

abcxxxxabcxabcd
abcdxabcxxxxabcx

样例输出

11

提示

" abcxxxxabcx" 是第一个字符串的前缀和第二个字符串的后缀。

来源
USACO2009OCT

B.初步分析

及最长连续子串。
而此题若用DP(动态规划),实在太麻烦了。
那么现在应该怎么做呢?

#include
using namespace std;

int main(){
	char str1[81],str2[81];
	scanf("%s %s",&str1,&str2);
	//读入字符串,方法很简单
	 
	 
	int len1=strlen(str1);
	int len2=strlen(str2);
	//记录两个字符串的长度
	 
	 
	if(len1>len2){//保证后面的运算不会因两个字符串长短而变化 
		swap(len1,len2);//神神奇奇的函数swap交换两个数
		char str3[81];
		strcpy(str3,str2);
		strcpy(str2,str1);
		strcpy(str1,str3);
		//神神奇奇的函数strcpy交换两个字符串 
	} 
 	//思路:求连续的最长公共子串
	 
	  
	for(int i=len1;i>=1;i--){ //枚举子串长度i,i从后往前算,更节约时间(如下所讲)
		//做好最坏的打算,时间复杂度O(80) 
		for(int j=0;j<=len1-i+1;j++){//别忘了0
			//<=O(80) 
			for(int k=0;k<=len2-i+1;k++){
				//<=O(80) 
				
				int fl=1;//fl一定要初始化 
				
				for(int lj=j,lk=k,li=1;li<=i;lj++,lk++,li++){
					//<=O(80)
					if(str1[lj]!=str2[lk]){
						fl=0;
						break;//警觉的态度,用时会下降 
					}
				}
				
				if(fl==1){
					printf("%d",i);//因为i最长,所以完全放心 
					return 0;//最厉害的一招:不需要break跳出,直接终结程序 
				}
			}
		}
	}
	//时间复杂度<=O(512000) 
} 

C.提高组拓展解法

string解法:

#include 
using namespace std; 

string a, b;

int main() {
	cin>>a>>b;
	for (int y = 0; y <= a.size() - x;y++) {
		string C = a.substr(y, x);
		if (b.find(c) != -1) {
			cout<< x;
			return 0;
		}
	}
}

你可能感兴趣的:(信息学竞赛真题堆,#,USACO堆)