USACO 2.3.1 Longest Prefix
题目意思就是给定1~200个短的Primitive (长度1~10),以及一个长字符串 (长度200,000以内),需要找出由这些Primitive任意重复连接形成的后者的最长前缀。
DP + Trie
设长字符串为seq,基本思路是若seq[0…i]是满足要求的前缀,那么seq[0…i+len]也是满足要求的前缀,len是各个Primitive的长度。
然后就是用Trie优化一下判断seq[i…i+len]是否在Primitive集合的过程。
/*
ID: xjtuacm1
PROG: prefix
LANG: C++
*/
#include<iostream>
#include<stack>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
const int PRISIZE = 205;
const int PRILEN = 10 + 1;
const int SEQLEN = 200005;
const int LINELEN = 76 + 2;
struct _trie
{
int next[26];
int cnt;
} trie[PRISIZE * PRILEN];
int trieNodeCnt;
int trieInit()
{
memset(trie, 0, sizeof(trie));
trieNodeCnt = 1;
return 0; // trie tree's root
}
void trieAdd(int root, const char *str)
{
int p = root;
while(*str)
{
if(trie[p].next[*str - 'A'] == 0)
{
trie[p].next[*str - 'A'] = trieNodeCnt++;
}
p = trie[p].next[*str - 'A'];
str++;
}
trie[p].cnt += 1;
}
bool trieSearch(int root, const char* str, int len)
{
int p = root;
for(int i = 0; i!= len; i++)
{
if(trie[p].next[str[i] - 'A'] == 0)
return false;
p = trie[p].next[str[i] - 'A'];
}
return trie[p].cnt > 0;
}
char seq[SEQLEN];
int seqlen = 0;
bool reach[SEQLEN]; // reach[i] = if seq[0...i) (length = i) can be composed from primitives.
int main(int argc, char *argv[])
{
freopen("prefix.in", "r", stdin);
#ifndef USACO
freopen("prefix.out", "w", stdout);
#endif // USACO
int root = trieInit(); // root = 0
memset(reach, false, sizeof(reach));
char temp[PRILEN];
for(int i = 0; i!= PRISIZE; i++)
{
scanf("%s", temp);
if(temp[0] == '.')
break;
trieAdd(root, temp);
}
while(true)
{
scanf("%s", seq + seqlen);
int len = strlen(seq + seqlen);
if(len == 0)
break;
seqlen += len;
}
for(int i = 1; i!= PRILEN; i++)
{
reach[i] = trieSearch(root, seq, i);
}
for(int i = 0; i!= seqlen; i++)
{
if(reach[i])
{
for(int j = 1; j!= PRILEN; j++)
{
if(trieSearch(root, seq + i, j))
reach[i + j] = true;
}
}
}
for(int i = seqlen ; i != 0; i--)
{
if(reach[i])
{
printf("%d\n", i);
return 0;
}
}
printf("0\n");
return 0;
}
BTW,这是我第一次写Trie,感觉还挺顺手的。