题目描述
在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的序列(即元素)很感兴趣。
如果一个集合 P 中的元素可以串起来(元素可以重复使用)组成一个序列 s ,那么我们认为序列 s 可以分解为 P 中的元素。元素不一定要全部出现(如下例中 BBC
就没有出现)。举个例子,序列 ABABACABAAB
可以分解为下面集合中的元素:{A,AB,BA,CA,BBC}
序列 s 的前面 k 个字符称作 s 中长度为 k 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列 ,设 ′s′ 是序列 s 的最长前缀,使其可以分解为给出的集合 P 中的元素,求 ′s′ 的长度 k。
输入格式
输入数据的开头包括若干个元素组成的集合 O,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 .
的行,集合中的元素没有重复。
接着是大写字母序列 s ,长度为,用一行或者多行的字符串来表示,每行不超过 7676 个字符。换行符并不是序列 s 的一部分。
输出格式
只有一行,输出一个整数,表示 S 符合条件的前缀的最大长度。
输入输出样例
输入
A AB BA CA BBC . ABABACABAABC
输出
11
说明/提示
【数据范围】
对于 100% 的数据,1≤card(P)≤200,1≤∣S∣≤2×105,P 中的元素长度均不超过 10。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=4e4+10;
const int N=3e5+10;
string s[N];
int Next[N];
int sum[N];
int n,m,k;
void getNext(string str)
{
memset(Next,0,sizeof(Next));
Next[0]=-1;
Next[1]=0;
int i=2;
int cn=0;
while(i<str.size())
{
if(str[i-1]==str[cn])
Next[i++]=++cn;
else if(cn>0)
cn=Next[cn];
else
Next[i++]=0;
}
}
void KMP(string str1,string str2)
{
int i1=0,i2=0;
getNext(str2);
int res=0;
while(i1<str1.size())
{
if(str1[i1]==str2[i2])
{
i1++;
i2++;
}
else if(i2==0)
i1++;
else
i2=Next[i2];
if(i2==str2.size())
{
sum[i1]--;
sum[i1-str2.size()]++;
i2=Next[i2];
}
}
}
void solve()
{
while(cin>>s[++k])
{
if(s[k]==".")
break;
}
k--;
string str,str1;
while(cin>>str)
{
str1+=str;
}
for(int i=1;i<=k;i++)
KMP(str1,s[i]);
for(int j=0;j<str1.size();j++)
{
if(j==0)
continue;
sum[j]=sum[j-1]+sum[j];
}
int j;
for(j=0;j<str1.size();j++)
{
if(sum[j]<=0)
{
cout<<j<<endl;
return ;
}
}
if(j==str1.size())
cout<<j<<endl;
return ;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
ll t=1;
// cin>>t;
while(t--)
{
solve();
}
return 0;
}