USACO 2.31 The Longest Prefix

描述

在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。

如果一个集合 P 中的元素可以通过串联(元素可以重复使用,相当于 Pascal 中的 “+” 运算符)组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素。元素不一定要全部出现(如BBC就没有出现)。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:

{A, AB, BA, CA, BBC}

序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 S ,设S'是序列S的最长前缀,使其可以分解为给出的集合P中的元素,求S'的长度K。

格式

PROGRAM NAME: prefix

INPUT FORMAT

输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 “.” 的行。集合中的元素没有重复。接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串来表示,每行不超过 76 个字符。换行符并不是序列 S 的一部分。

OUTPUT FORMAT

只有一行,输出一个整数,表示 S 符合条件的前缀的最大长度。

SAMPLE INPUT (file prefix.in)

A AB BA CA BBC
.
ABABACABAABC

SAMPLE OUTPUT (file prefix.out)

11
 
分析:一开始觉得,trie+dfs+kmp好经典的呀,可惜对这题目而已,效率太低了,果断TLE;
之后,用DP做的,这个思想就比较简单了,dp[i]表示当前位置是否可达,
状态转移方程:dp[i+len[j]]=dp[i];(0<=j<m) j表示当前的字典里的元素
#include<iostream>
#include<algorithm>
#include<string.h>
#include<fstream>
using namespace std;
struct dic
{
	char str[11];
	int len;
}d[210];
char s[200100];
bool dp[200200]={0};
bool cmp(dic a,dic b)
{
	return a.len>b.len;
}
int main()
{
	freopen("prefix.in","r",stdin);
	freopen("prefix.out","w",stdout);
	char str[11],str2[80];
	int m=0;
	while(scanf("%s",str)==1)
	{
		if(strcmp(str,".")==0)
			break;
		strcpy(d[m].str,str);
		d[m++].len=strlen(str);
	}
//	sort(d,d+m);
	s[0]='\0';
	while(cin>>str2)
		strcat(s,str2);
	int len1=strlen(s);
	dp[0]=1;
	int ans=0;
	for(int i=0;i<len1;i++)
	{
		if(!dp[i]) continue;
		for(int j=0;j<m;j++)
		{
			int flag=0;
			for(int k=0;k<d[j].len;k++)
			{
				if(d[j].str[k]!=s[i+k])
				{
					flag=1;break;
				}
			}
			if(!flag) {
				dp[i+d[j].len]=1;
				if(i+d[j].len>ans)
					ans=i+d[j].len;
			}
		}
	}
	cout<<ans<<endl;
}

 下面这个是一开始超时的代码

#include<iostream>
#include<algorithm>
#include<fstream>
#include<string.h>
using namespace std;
typedef struct node  
{  
    node *next[26];  
    int v;  
}*tree,t;  
tree root;  
int ans;
char str[200010];
void insert(char *s)  
{  
    tree p=root,newnode;  
    for(;*s!='\0';s++)  
    {  
        int d=*s-'A';  
        if(p->next[d]!=NULL)  
            p=p->next[d];  
        else  
        {  
            newnode=(tree)malloc(sizeof(t));  
            for(int i=0;i<26;i++)  
                newnode->next[i]=NULL;  
            newnode->v=-1;   
            p->next[d]=newnode;  
            p=newnode;  
        }  
    }  
    p->v=1;  
}  
void dfs(char *s,int cnt)
{
	tree p=root;
	char *s1=s;
	if(cnt>ans)
		ans=cnt;
//	cout<<s<<endl;
//	cout<<cnt<<endl;
	for(int i=1;*s1!='\0';s1++,i++)
	{
		int d=*s1-'A';
		p=p->next[d];
		if(p==NULL)
			return;	
	//	cout<<d<<' '<<p->v<<endl;
		if(p->v==1)
		{
		//	cout<<"long "<<i<<endl;
			dfs(s+i,cnt+i);
		}
	}
}
int main()
{
	char str1[20],str2[76];
    root=(tree)malloc(sizeof(t));  
    for(int i=0;i<26;i++)  
        root->next[i]=NULL;  
    root->v=-1;  
	freopen("prefix.in","r",stdin);
	freopen("prefix.out","w",stdout);
	while(scanf("%s",str1)==1)
	{
		if(strcmp(str1,".")==0)
			break;
		insert(str1);
	}
	ans=0;
	str[0]='\0';
	while(cin>>str2)
		strcat(str,str2);
//	cin>>str;
	dfs(str,0);
	cout<<ans<<endl;
	return 0;
}

 

posted @ 2011-11-16 10:58  枕边梦  阅读(563)  评论(0编辑  收藏  举报