USACO 2.3 Longest Prefix 题解

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 于家中

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值