这道题困扰了我两个月,终于还是用trie图的方法做出来了。
题目3 : giftscount
时间限制:8000ms
单点时限:1000ms
内存限制:256MB
描述
网易CC里,有很多礼物(总数<1000种礼物),每一种礼物都有一个编号ID,系统里使用1到10位的数字串(其实是字符串,只不过刚好是数字而已)来表示这个ID,如3个礼物ID:{44, 45, 470}。
其中礼物又分为付费礼物与免费礼物。现在我们将一小时内,当前主播收到的所有礼物(付费+免费)的ID串起来,就形成了一个很大的数字串V(总长度<20000)。
现在给定一个全部由礼物ID合成的串V,计算里面最多有多少次付费礼物的消费。
如付费礼物ID表:S = {12,3,4,44,45,470}
全部由礼物ID合成的数字串V:V = 1434512412744
最多可以由 8 个礼物组成。分别为: 4, 3, 45, 12, 4, 12,4,4这8次付费礼物的消费。
输入
第1行输入付费礼物个数,N
接下来N行(第2到第N+1行)输入每个付费礼物的ID。1<= ID的长度 <10位。
最后一行输入礼物ID串V
输出
最多送了多少个付费礼物。
样例输入
6
12
3
4
44
45
470
1434512412744
样例输出
8
#include<iostream>
#include<string>
#include<queue>
using namespace std;
struct trie{
int flag;
struct trie *next[10];
struct trie *suffix;
trie(){
flag=0;
memset(next,NULL,sizeof(next));
suffix=NULL;
}
};
void build(trie *root,string &s)
{
trie *cur=root;
int len=s.length();
for(int i=0;i<len;++i)
{
int id=s[i]-'0';
if(!cur->next[id]){
trie *nn=new trie();
cur->next[id]=nn;
}
cur=cur->next[id];
}
cur->flag=1;
}
int main()
{
int n;
cin>>n;
string s;
trie *root=new trie();
while(n--)
{
cin>>s;
build(root,s);
}
root->suffix=root;
queue<trie *> qt;
for(int i=0;i<10;++i){
if(!root->next[i])
root->next[i]=root;
else{
root->next[i]->suffix=root;
qt.push(root->next[i]);
}
}
trie *cur,*suf;
while(!qt.empty())
{
cur=qt.front();
suf=cur->suffix;
qt.pop();
for(int i=0;i<10;++i)
{
if(!cur->next[i])
cur->next[i]=suf->next[i];
else{
cur->next[i]->suffix=suf->next[i];
qt.push(cur->next[i]);
}
}
}
cin>>s;
int len=s.length(),count=0;
cur=root;
for(int i=0;i<len;++i)
{
int id=s[i]-'0';
cur=cur->next[id];
if(cur->flag){
count++;
cur=root; //加上这个条件是因为不能重复计算(例如:45只能算一种,不能算4和45两种)
}
}
cout<<count<<endl;
return 0;
}