此题可以用STL中的map做,但是了解一下Trie树这个数据结构也是必须的。
Trie树(又称字典树)有以下特点:
-
根节点不包含字符,除它之外的每一个节点都包含一个字符。
-
从根节点到某一节点,路径上经过所有字符连起来为该节点对应字符串
-
每个节点的子节点包含字符不同,也就意味着字符是可以公用的
于是我们用这样一个结构体表示每一个节点:
在本题中可以用动态数组vector贮存每个子节点
struct node{
char c;//该点对应字符
vector<struct node*>s;//储存儿子
int tag;//标记是否为某一字符串结尾
int rep; //应题目要求判断是否重复
}*root=new struct node;
当然字典树有两个函数必不可少,分别是add(插入)和query(查询)。
具体怎么实现还看代码:
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
using namespace std;
struct node{
char c;
vector<struct node*>s;
int tag;
int rep;
}*root=new struct node;
void add(string str)
{
struct node*p=root;
for(int i=0;i<str.length();i++)
{
int j;
for(j=0;j<p->s.size();j++)
if(p->s[j]->c==str[i])break;//如果找到对应公用字符
if(j==p->s.size())//如果遍历完后没找到新建一个
{
struct node *newnode =new struct node;
newnode->c=str[i];
newnode->s.clear();
newnode->tag=0;
newnode->rep=0;
p->s.push_back(newnode);
p=newnode;
}
else p=p->s[j];
}
p->tag=1;//标志此节点为一字符串结尾
}
int query(string str)
{
struct node*p=root;
for(int i=0;i<str.length();i++)
{
int j;
for(j=0;j<p->s.size();j++)
if(p->s[j]->c==str[i])
{break;}
if(j==p->s.size()) //如果遍历完后没找到
return 0;
p=p->s[j];
}
if(p->rep!=3)
{
p->rep=3;return p->tag;//找到的字符可能只是某一前缀而非整个字符串,所以需要一个tag标记
}
else if(p->rep==3)return p->rep;
}
int main()
{
int n,m;
char tag[50];
cin>>n;
root->s.clear();
for(int i=1;i<=n;i++)
{
string str;
cin>>str;
add(str);
}
cin>>m;
for(int i=1;i<=m;i++)
{
string str;
cin>>str;
int flag=query(str);
if(flag==0)puts("WRONG");
else if(flag==1)puts("OK");
else if(flag==3)puts("REPEAT");
}
return 0;
}