vj地址
一共9题
题意:给很多字符串,然后在这些串中查询公共前缀的数量
分析:字典树模板题
//from : 1610300216
#include
#include
using namespace std;
#include
#include
#include
#include
const int maxn = 26;
struct Trie
{
Trie *Next[maxn];
int sum;//jishu
Trie()
{
sum = 0;
for(int i = 0; i < maxn; i++)
Next[i] = NULL;
}
};
Trie *root;
void CreatTrie(char *str)
{
int len = strlen(str);
len --; //因为主函数里读取字符串用的是fgets,会把'\n'读进去,故len--
Trie *p = root, *q;
for(int i = 0; i < len; i++)
{
int id = str[i] - 'a';// 求下标。ASC表的如 b-a 等于1
if(p->Next[id] == NULL)
{//空表时
q = new Trie();
q->sum = 1;
p->Next[id] = q;
p = p->Next[id];
}
else
{
p->Next[id]->sum ++; //不是空表,记录出现次数
p = p->Next[id];
}
}
}
int FindTrie(char *str)
{
int len = strlen(str);
Trie *p = root;
for(int i = 0; i < len; i++)
{
int id = str[i] - 'a'; //同上
if(p->Next[id] == NULL)
return 0;
else p = p->Next[id];
}
return p->sum;
}
void release(Trie *p)
{
if(p==NULL)
return ;
for(int i = 0; i < maxn; i++)
if(p->Next[i]!=NULL)
release(p->Next[i]);
free(p);
root=NULL;
return ;
}
int main()
{
char str[15];
root = new Trie(); // root要给新空间
while(fgets(str,15,stdin) && strcmp(str,"\n") != 0) //“stdin”标准输入,从键盘输入
{
CreatTrie(str);
}
while(scanf("%s",str) != EOF)
{
int total = FindTrie(str);
printf("%d\n",total);
}
release(root);
return 0;
}
题意:有很多字符串,问有没有串是别的串的前缀。
分析:这里在字典树的建树中就可以判断出来了。若字符串A是B的前缀,有两种可能,若B先建树,A建树的过程中是没有节点为空的,也就是不会新建节点。若A先建树,B在建树的过程中就会经过A。
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 5
#define LL long long
struct Trie
{
int v;
Trie *next[maxn];
Trie()
{
v=0;
for(int i=0;iint sert(char *str)
{
int g=0,flag=0;
int len=strlen(str);
Trie *p=root;
for(int i=0;iint id=str[i]-'0';
if(p->next[id]==NULL)
{
g=1;//新建节点
p->next[id]=new Trie;
}
p=p->next[id];
if(p->v) flag=1;//有没有经过别的字符串
}
p->v=1;
if(flag==1||g==0) return 0;
else return 1;
}
void del(Trie *p)
{
if(p==NULL) return ;
for(int i=0;iif(p->next!=NULL) del(p->next[i]);
}
delete p;
}
int main()
{
char s[20];
root=new Trie;
int gg=0;
int case1=1;
while(scanf("%s",s)!=EOF)
{
if(s[0]=='9') {
if(gg) printf("Set %d is not immediately decodable\n",case1++);
else printf("Set %d is immediately decodable\n",case1++);
del(root);
root=new Trie;
gg=0;
continue;
}
if(!sert(s)) gg=1;
}
return 0;
}
题意 :一本英文-火星的字典,给你几组英文和火星文的字符串,给你一句火星文,翻译出来,如果字典里没有那句火星文的话,直接将火星文输出。字典里的字符都是小写英文字母;
分析:将字典中的火星词建树,然后将对应的英文词存起来。翻译的时候直接在树上找就好了。这里注意一下字符串的处理就行了
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define maxn 26
#define LL long long
char s[3000000][15];
struct Trie
{
int v;
Trie *next[maxn];
Trie()
{
v=0;
for(int i=0;ivoid sert(char *str,int h)
{
int len=strlen(str);
Trie *p=root;
for(int i=0;iint id=str[i]-'a';
if(p->next[id]==NULL)
p->next[id]=new Trie;
p=p->next[id];
}
p->v=h;
}
void del(Trie *p)
{
if(p==NULL) return ;
for(int i=0;iif(p->next!=NULL) del(p->next[i]);
}
delete p;
}
int findf(char *str)
{
int len=strlen(str);
Trie *p=root;
for(int i=0;iint id=str[i]-'a';
if(p->next[id]==NULL) return 0;
p=p->next[id];
}
if(p->v==0) return 0;
else {
printf("%s",s[p->v]);
return 1;
}
}
int main()
{
char s1[15],s2[15];
int h=1;
root=new Trie;
while(scanf("%s",s[h]))
{
if(strcmp(s[h],"START")==0) continue;
else if(strcmp(s[h],"END")==0) break;
scanf("%s",s2);
sert(s2,h);h++;
}
char c,g=0;
getchar();
c=getchar();
while(1)
{
while(c>='a'&&c<='z'){
s2[g++]=c;
c=getchar();
}
s2[g]='\0';
if(g>0) {
if(!findf(s2)) printf("%s",s2);
g=0;
}
else if(c=='S')
{
for(int i=0;i<6;i++) c=getchar();
}
else if(c=='E') {
getchar();getchar();getchar();break;
}
else {printf("%c",c);c=getchar();}
}
del(root);
return 0;
}
也可以用map
//from : 742962178
#include
#include
#include
#include
#include
using namespace std;
int main()
{
map<string, string> m;
char s1[10],s2[10];
char temp[10];
string str;
while (scanf("%s",s1)) {
if (s1[0] == 'S')
scanf("%s", s1);
if (s1[0] == 'E')
break;
scanf("%s", s2);
m[s2] = s1;
}
scanf("%s", temp);
getchar();
char ch=' ';
while (scanf("%c",&ch)) {
if (isalpha(ch))
str += ch;
else {
if (str[0] == 'E')break;
if (m.find(str) != m.end())
cout << m[str];
else cout << str;
printf("%c", ch);
str.clear();
}
}
return 0;
}
题意: 有很多字符串,问其中哪个字符串是有其他两个字符串组成的
分析:先将全部字符串都建树,然后将每个字符串分成两个字符串在字典树中查找,如果都找到了,就是它~~
//from : Next
#include
#include
#include
#include
using namespace std;
#define mx 26
#define mxn 26
typedef struct Trie
{
Trie *next[mx];
int v;
Trie()
{
v=0;
for(int i=0; ichar s[50003][117],p[mxn];
Trie *root;
void creTrie(char *s)
{
int len=strlen(s);
Trie *p=root,*q;
// len--;
for(int i=0; iint id=s[i]-'a';
if(p->next[id]==NULL)
{
q=new Trie();
q->v=1;
for(int j=0; jnext[j]=NULL;
p->next[id]=q;
p=p->next[id];
}
else
{
//p->next[id]->v++;
p=p->next[id];
}
}
p->v=-1;
}
int searchs(char* rp)
{
int len=strlen(rp);
Trie *p=root;
for(int i=0; iint id=rp[i]-'a';
p=p->next[id];
if(p==NULL)return 0;
// else return 0;
}
if(p->v==-1)return-1;
else return 0;
}
void dealTrie(Trie* t)
{
if(t==NULL)return;
for(int i=0; iif(t->next[i]!=NULL)dealTrie(t->next[i]);
free(t);
root=NULL;
return;
}
int main()
{
root=new Trie();
int cnt=0;
while(scanf("%s",s[cnt])!=EOF)
{
creTrie(s[cnt]);cnt++;
}
char a[103],b[103];
for(int i=0; iint len = strlen(s[i]);
for(int j=1; jmemset(a,'\0',sizeof(a));
memset(b,'\0',sizeof(b));
strncpy(a,s[i],j);
strncpy(b,s[i]+j,len-j);
if(searchs(a)==-1&&searchs(b)==-1)
{
cout<break;
}
}
}
return 0;
}
这一题竟然和B题一模一样,惊不惊喜。。改一点点就可以交了~~
题意:给n个字符串,有q个提问,问这个字符串在给的n个字符串中有没有出现过。
分析:先将n个字符串建树,每个字符串,如s[0,1,2,…len-1],将s[0,1,2,…len-1],s[1,2,…len-1],s[2,3…len-1],一直到s[len-1]建树。然后在字典树种每个字符串出现的次数记录一下,注意,由同一个字符串建树,出现的次数应该为1.比如abab,这里a出现的次数应该是1。最后查询即可
//from : caijichang
#include
#include
#include
using namespace std;
struct trie{
int v;
int m; //是否重复;
trie *next[26];
trie(){
v=0;
for(int i=0;i<26;i++)
{
m=-1;
v=0;
next[i]=NULL;
}
}
};
trie *root;
void creat(trie *root,char *str,int k)
{
trie *p=root;
for(;*str;str++)
{
int sign=*str-'a';
if(p->next[sign]==NULL)
{
p->next[sign]=new trie();
}
p=p->next[sign];
if(p->m!=k)
{
p->m=k;
p->v++;
}
}
}
int find(trie *root,char *str)
{
int len=strlen(str);
trie *p=root;
for(int i=0;iint id=str[i]-'a';
if(p->next[id]==NULL)
{
return 0;
}
p=p->next[id];
}
return p->v;
}
void del(trie *root)
{
for(int i=0;i<26;i++)
{
if(root->next[i])
{
del(root->next[i]);
}
}
delete(root);
}
int main()
{
int n,m;
char s[30];
root=new trie();
cin>>n;
while(n--)
{
scanf("%s",s);
for(int j=0;j<strlen(s);j++)
{
creat(root,s+j,n);
}
}
cin>>m;
while(m--)
{
scanf("%s",s);
cout<return 0;
}
题意:中文题,应该看得懂~
分析:主要是删除这操作,找到那个点后,我们要删掉后面的,也要删掉前面的。
//from : 742962178
#include
#include
#include
#include
using namespace std;
const int maxn = 26;
struct Trie
{
Trie *next[maxn];
int v;
Trie() {
v = 0;
memset(next, NULL, sizeof(next));
}
};
Trie* root;
void insertTrie(string str)
{
int len = str.size();
Trie *p = root;
for (int i = 0; i < len; i++) {
int id = str[i] - 'a';
if (!p->next[id]) {
p->next[id] = new Trie();
p->next[id]->v = 1;
p = p->next[id];
}
else {
p->next[id]->v++;
p = p->next[id];
}
}
}
void release(Trie *p)
{
if (p == NULL)
return;
for (int i = 0; iif (p->next[i])
release(p->next[i]);
p = NULL;
delete p;
return;
}
void deleteTrie(string str)
{
int len = str.size();
Trie *p = root, *pre;
int i = 0;
for (i = 0; i < len; i++) {
int id = str[i] - 'a';
if (p->next[id]) {
pre = p;
p = p->next[id];
}
else break;
}
if (str[i] == '\0') {
int num = p->v;
Trie *q = root;
release(p);
pre->next[str[len - 1] - 'a'] = NULL;
for (int i = 0; i < len - 1; i++) {
q = q->next[str[i] - 'a'];
q->v -= num;
}
}
}
void searchTrie(string str)
{
int len = str.size();
Trie *p = root;
for (int i = 0; i < len; i++) {
int id = str[i] - 'a';
if (!p->next[id]) {
printf("No\n");
return;
}
p = p->next[id];
}
if (p->v < 1)
printf("No\n");
else printf("Yes\n");
return;
}
int main()
{
int n = 0;
scanf("%d", &n);
root = new Trie();
while (n--) {
char s1[10];
char s2[35];
scanf("%s%s", s1, s2);
switch (s1[0])
{
case 'i':insertTrie(s2); break;
case 's':searchTrie(s2); break;
case 'd':deleteTrie(s2); break;
default:
break;
}
}
release(root);
return 0;
}
后面两题就直接上代码了…
//from : caijichang
#include
#include
#include
using namespace std;
char s[20];
char s1[100005][20];
int num=1;
struct trie{
int v;
trie *next[26];
trie(){
for(int i=0;i<26;i++)
{
v=0;
next[i]=NULL;
}
}
};
trie *root;
bool flag;
void creat(trie *root,char *str)
{
int len=strlen(str);
trie *p=root,*q;
for(int i=0;iint sign=str[i]-'a';
if(p->next[sign]==NULL)
{
q=new trie();
p->next[sign]=q;
p=p->next[sign];
}
else
{
p=p->next[sign];
}
}
p->v=num;
num++;
}
int find(trie *root,char *str)
{
int len=strlen(str);
trie *p=root;
for(int i=0;iint id=str[i]-'a';
p=p->next[id];
if(p==NULL)
{
cout<<"eh"<return 0;
}
}
return p->v;
}
void del(trie *root)
{
for(int i=0;i<26;i++)
{
if(root->next[i])
{
del(root->next[i]);
}
}
delete(root);
}
int main()
{
root=new trie();
int count=0;
char str1[50];
while(gets(str1))
{
if(str1[0]=='\0')
break;
sscanf(str1,"%s%s",s1[count],s);
count++;
creat(root,s);
}
while(scanf("%s",s)!=EOF)
{
int n=find(root,s);
if(n>0)
{
cout<1]<return 0;
}
//from : 742962178
#include
#include
#include
using namespace std;
const int maxn = 26;
struct Trie
{
Trie *next[maxn];
int v;
Trie() {
v = 0;
memset(next, NULL, sizeof(next));
}
};
Trie *root;
void createTrie(string str)
{
int len = str.size();
Trie* p = root, *q;
for (int i = 0; i < len; i++) {
int id = str[i] - 'a';
if (p->next[id] == NULL) {
p->next[id] = new Trie();
p->next[id]->v = 1;
p = p->next[id];
}
else {
p->next[id]->v++;
p = p->next[id];
}
}
}
string findTrie(string str)
{
int len = str.size();
Trie *p = root;
for (int i = 0; i < len; i++) {
int id = str[i] - 'a';
if (p->next[id] != NULL) {
p = p->next[id];
if (p->v == 1)
return string(str.begin(), str.begin()+i+1);
}
}
return str;
}
void release(Trie *p)
{
if (p == NULL)
return;
for (int i = 0; iif (p->next[i] != NULL)
release(p->next[i]);
free(p);
root = NULL;
return;
}
int main()
{
string s[1005];
int n = 0;
root = new Trie();
while (cin >> s[n++]) {
createTrie(s[n - 1]);
}
for (int i = 0; i < n; i++) {
cout << s[i] <<" "<< findTrie(s[i]) << endl;
}
release(root);
return 0;
}