Longest Prefix
FROM: IOI’96
PROBLEM DESCRIPTION:
The structure of some biological objects is represented by the sequence of their constituents, where each part is denoted by an uppercase letter. Biologists are interested in decomposing a long sequence into shorter sequences called primitives.
We say that a sequence S can be composed from a given set of primitives P if there is a some sequence of (possibly repeated) primitives from the set whose concatenation equals S. Not necessarily all primitives need be present. For instance the sequence ABABACABAAB can be composed from the set of primitive : {A, AB, BA, CA, BBC}
The first K characters of S are the prefix of S with length K. Write a program which accepts as input a set of primitives and a sequence of constituents and then computes the length of the longest prefix that can be composed from primitives.
PROGRAM NAME: prefix
INPUT FORMAT
First, the input file contains the list (length 1..200) of primitives (length 1..10) expressed as a series of space-separated strings of upper-case characters on one or more lines. The list of primitives is terminated by a line that contains nothing more than a period (`.'). No primitive appears twice in the list. Then, the input file contains a sequence S (length 1..200,000) expressed as one or more lines, none of which exceeds 76 letters in length. The "newlines" (line terminators) are not part of the string S.
SAMPLE INPUT (file prefix.in)
A AB BA CA BBC
.
ABABACABAABC
OUTPUT FORMAT
A single line containing an integer that is the length of the longest prefix that can be composed from the set P.
SAMPLE OUTPUT (file prefix.out)
11
THOUGHTS:
难道不就是一个查询字符串吗?
博主的第一反应便是字典树(Trie)。
我们需要做的事就是建好树,然后从S首部开始搜索。每找到一个子串后就在相应位置处进行标记。
每个搜索开始的条件表示它的前一个位置被标记(S[0]处除外),因为要求是寻找最长的组合前缀。
DETAILS:
注意到了字符串的长度范围了吗?S.lenth ≤ 200,000。
那么我们使用scanf(“%s”, S)是不行的,原因大概是超出了它的限定长度。
·对于此,我们的解决办法是不停的读入,将每次读入的部分连接到S的尾部:
while(~scanf("%s", Sub) strcat(S, Sub);//将每次读入的Sub连接到S的尾部
DIFFICULTIES: pj+
AC PROGRAM:
/*
ID: kongse_1
PROG: prefix
LANG: C++
*/
// Skq_Liao
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (register int i = (a), i##_end_ = (b); i < i##_end_; ++i)
#define ROF(i, a, b) for (register int i = (a), i##_end_ = (b); i > i##_end_; --i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const char Fin[] = "prefix.in";
const char Fout[] = "prefix.out";
void In()
{
freopen(Fin, "r", stdin);
freopen(Fout, "w", stdout);
return ;
}
struct Trie{
Trie* Next[26];
bool flag;
Trie()
{
flag = 0;
memset(Next, 0, sizeof Next);
}
};
int Idx(char c)
{
return c - 'A';
}
void Build(Trie* cur, char *S)
{
char *s = S;
while(*s)
{
int id = Idx(*s++);
if(!cur->Next[id])
cur->Next[id] = new Trie();
cur = cur->Next[id];
}
cur->flag = true;
return ;
}
const int MAXN = 200000 + 0120;
int ll;
bool F[MAXN];
void Query(Trie* cur, char *S, int pos)
{
FOR(i, pos, ll)
{
int id = Idx(S[i]);
if(cur->Next[id])
cur = cur->Next[id];
else
return ;
if(cur->flag)
F[i] = cur->flag;
}
return ;
}
int main()
{
In();
Trie *root = new Trie();
char Sub[1 << 10], S[MAXN];
int ans = 0;
while(scanf("%s", Sub))
{
if(Sub[0] == '.')
break;
Build(root, Sub);
}
while(~scanf("%s", Sub))
strcat(S, Sub);
ll = strlen(S);
Query(root, S, 0);
FOR(i, 1, ll)
if(F[i - 1])
Query(root, S, i), ans = i;
if(F[ll - 1])
ans = ll;
printf("%d\n", ans);
return 0;
}
Skq_Liao 2017/07/10 20:25 于家中