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