状态表示:
(f(i)):前缀(s[1 sim i])能否由子串集合中的元素表示。
(f(i))只有(true)和(false)两种取值。
状态转移:
对每个子串(p[i]),若(s[i])大小为(p[i])长度的后缀与(p[i])匹配,则有如下转移:
[f(i) |= f(i-p[i].size())
]
const int N=2e5+10;
bool f[N];
string a[210];
string s;
int n;
int main()
{
while(cin>>s, s[0] != '.')
a[n++]=s;
s.clear();
string line;
while(cin>>line) s += line;
f[0]=true;
int res=0;
for(int i=1;i<=s.size();i++)
for(int j=0;j<n;j++)
{
int t=a[j].size();
if(i >= t && s.substr(i-t,t) == a[j])
f[i] |= f[i-t];
if(f[i]) res=i;
}
cout<<res<<endl;
//system("pause");
return 0;
}
判断某一后缀是否由子串集合中的元素组成,不必枚举所有子串,可以借助哈希表优化。由于子串的长度不超过(10),所以按长度从小到大枚举后缀,判断该后缀是否在哈希表(子串集合)中。
const int N=2e5+10;
bool f[N];
unordered_set<string> S;
string s;
int n;
int main()
{
while(cin>>s, s[0] != '.')
S.insert(s);
s.clear();
string line;
while(cin>>line) s += line;
f[0]=true;
int res=0;
for(int i=1;i<=s.size();i++)
for(int j=1;j<=min(i,10);j++)
{
string t=s.substr(i-j,j);
if(S.count(t))
f[i] |= f[i-j];
if(f[i]) res=i;
}
cout<<res<<endl;
//system("pause");
return 0;
}