描述
在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。
如果一个集合 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;
}