USACO SECTION 2.3 Longest Prefix

Longest Prefix
IOI'96

The structure of some biological objects is represented by the sequence of their constituents, where each part is denote by an uppercase letter. Biologists are interested in decomposing a long sequence into shorter ones calledprimitives.

We say that a sequence S can be composed from a given set of primitives P if there is a some sequence of (possibly repeated) primitives from the set whose concatenation equals S. Not necessarily all primitives need be present. For instance the sequenceABABACABAABcan be composed from the set of primitives

	   {A, AB, BA, CA, BBC}

The first K characters of S are the prefix of S with length K. Write a program which accepts as input a set of primitives and a sequence of constituents and then computes the length of the longest prefix that can be composed from primitives.

PROGRAM NAME: prefix

INPUT FORMAT

First, the input file contains the list (length 1..200) of primitives (length 1..10) expressed as a series of space-separated strings of upper-case characters on one or more lines. The list of primitives is terminated by a line that contains nothing more than a period (`.'). No primitive appears twice in the list. Then, the input file contains a sequence S (length 1..200,000) expressed as one or more lines, none of which exceeds 76 letters in length. The "newlines" (line terminators) are not part of the string S.

SAMPLE INPUT (file prefix.in)

A AB BA CA BBC
.
ABABACABAABC

OUTPUT FORMAT

A single line containing an integer that is the length of the longest prefix that can be composed from the set P.

SAMPLE OUTPUT (file prefix.out)

11

 

/*
ID: conicoc1
LANG: C
TASK: prefix
*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>


char str[200][100];
char temp[100];
char S[200000];
int Slenth;
int Answer[2][200];
int prefix=-1;

int judge(int i,int j)   //比较是否匹配
{
	int k;
	for(k=0;k<strlen(str[i]);k++)
	{
		if(S[Answer[0][j]+k]!=str[i][k])
			return 0;
	}
	return 1;
} 

int state()
{
	int i;
	for(i=0;i<Slenth;i++)
	{
		if(Answer[0][i]!=Answer[1][i])
			return 1;
	}
	return 0;
}
 
int main()
{
	FILE *fin,*fout;
	fin=fopen("prefix.in","r");
	fout=fopen("prefix.out","w");
	memset(str,'.',sizeof(str));
	int i=-1,j,k;
	
	do{
		i++;
		fscanf(fin,"%s",*(str+i));
	}while(str[i][0]!='.');
	Slenth=i;
	i=0;
	while(fscanf(fin,"%s",S+strlen(S))!=EOF);
	
	for(i=0;i<Slenth;i++)
	{
		Answer[0][i]=0;
	}
	//初始条件
	do
	{
		for(i=0;i<Slenth;i++)
		{
			Answer[0][i]=Answer[1][i];
		}
		for(i=0;i<Slenth;i++)
		{
			for(j=0;j<Slenth;j++)    //如果从Answer[j]位置开始后的和str[i]等长的字符串和str[i]相同,那么计算长度,如果更长,赋值
			{
				if(judge(i,j)&&Answer[0][j]+strlen(str[i])>Answer[0][i])
					Answer[1][i]=Answer[0][j]+strlen(str[i]);
			} 
			if(Answer[0][i]>prefix)
				prefix=Answer[0][i];
		}
	}while(state());
	
	fprintf(fout,"%d\n",prefix);
	return 0;
}


 

DP方程:

F( i ,j ) = Max( F( i -1 , k ) ) +H( j )     0<=k<=元素个数-1   H( j )表示 j 元素的长度, F( i,j )表示选择i个元素后,最后选择的元素是 j 时的前缀长度。

还要判断k与此时S所在位置后的字符串是否匹配

这样的动态规划显然不好啊。。

去研究研究题解。。。

 

经过研究

Analysis上的DP是

f(i)表示S的前i个是否为prefix

f[i]=(f[i-length(元素k)])  要求条件:strcmp(S中i到j ,元素k)==0

 

NOCOW上还介绍了一种

设f(i)为从i开始能匹配的最大长度  f(1)为所求答案

DP方程: f(i)=Max(f(j)+j-i)     i<j <S的长度&&存在长度为j-i的元素&&该元素与S中i-j匹配

 

其实上面两个一个从前开始一个从后开始,本质是一样的

 

下面介绍传说中的Trie树,又叫单词查找树或者键树

 

ADT的声明是这样的:

struct TrieTree
{
      struct TrieTree *Next[24];
      int Cnt;
};                                 //Cnt中保存单词的ASCII码,指针指向下面的24个字母


每插入一个单词,从头节点开始遍历,如果字母存在,那么再继续从该字母处开始遍历直到不存在,之后分配空间.

用这种方法匹配单词可以提高时间和空间效率,不需要在再每个单词遍历直到找到可行的情况了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值