P1809【USACO2.3.1】Longest Prefix最長前綴 IOI’96
時間限制 : 15000 MS 空間限制 : 65536 KB
問題描述
在生物學中,一些生物的結構是用包含其要素的大寫字母序列來表示的。生物學家對於把長的序列分解成較短的序列(即元素)很感興趣。
如果一個集合 P 中的元素可以通過串聯(元素可以重複使用,相當於 Pascal 中的 “+” 運算符)組成一個序列 S ,那麼我們認爲序列 S 可以分解爲 P 中的元素。元素不一定要全部出現(如下例中BBC就沒有出現)。舉個例子,序列 ABABACABAAB 可以分解爲下面集合中的元素:
{A, AB, BA, CA, BBC}
序列 S 的前面 K 個字符稱作 S 中長度爲 K 的前綴。設計一個程序,輸入一個元素集合以及一個大寫字母序列 S ,設S’是序列S的最長前綴,使其可以分解爲給出的集合P中的元素,求S’的長度K。
輸入格式
輸入數據的開頭包括 1..200 個元素(長度爲 1..10 )組成的集合,用連續的以空格分開的字符串表示。字母全部是大寫,數據可能不止一行。元素集合結束的標誌是一個只包含一個 “.” 的行。集合中的元素沒有重複。接着是大寫字母序列 S ,長度爲 1..200,000 ,用一行或者多行的字符串來表示,每行不超過
76 個字符。換行符並不是序列 S 的一部分。
輸出格式
只有一行,輸出一個整數,表示 S 符合條件的前綴的最大長度。
樣例輸入
A AB BA CA BBC
.
ABABACABAABC
樣例輸出
11
#include<cstdio>
#include<cstring>
#include<string.h>
#include<iostream>
using namespace std;
string a[201];
string str;
bool f[200001];
int n,len;
bool ischar(char c)
{
if(c>='A'&&c<='Z')
return true;
return false;
}
bool check(int p)
{
int t;
for(int i=1;i<=n;i++)
{
t=a[i].length();
if(p>=t)
{
if(a[i]==str.substr(p-t+1,t))
if(f[p-t])
return true;
}
}
return false;
}
int main()
{
string s;
n=0;
while(cin>>s,s!=".")
{
n++;
a[n]=s;
}
int x1,x2;
str="";
len=0;
while(cin>>s)
{
x1=0;
x2=s.length()-1;
while(!ischar(s[x1]))
x1++;
while(!ischar(s[x2]))
x2--;
str+=s.substr(x1,x2-x1+1);
len+=x2-x1+1;
}
memset(f,0,sizeof(f));
f[0]=true;
for(int i=1;i<=len;i++)
if(check(i))
f[i]=true;
else
f[i]=false;
for(int i=len;i>=0;i--)
if(f[i]){
cout<<i<<endl;
break;
}
return 0;
}