poj 2001
题意:给你一堆字符串,要求能够唯一识别该字符串的最短前缀。
(字典树+静态数组)
类似于poj3283。
在每个节点域里面加一个repeated,建立字典树的时候,repeated=false
该节点再次被访问时repeated=true
于是对每一个字串,依字典树遍历每个节点遇到repeated=false 则表示是最短前缀。
code:
#include<algorithm>
#include<iostream>
#include<string>
#include<cstdlib>
#include<cmath>
using namespace std;
#define N 2000
struct ROOT{
char letter;
int child,brother;
bool repeated;
}root[N*20+5];
struct STR{
char str[25];
}Letter[N+5];
int e;
bool builted(int &pre,char str[],int k,int n)
{// left is child ; right is brother
if(k==n)return true;
if(pre==-1)
{//查找不成功就添加
root[++e].letter=str[k];
root[e].repeated=false;
root[e].child=-1;
root[e].brother=-1;
pre=e;
builted(root[pre].child,str,k+1,n);
return false;
}
if(root[pre].letter == str[k])
{
root[pre].repeated=true;
return builted(root[pre].child,str,k+1,n);
}
int i;
for(i=pre;root[i].brother!=-1;i=root[i].brother)
if( root[root[i].brother].letter == str[k])
{
root[root[i].brother].repeated=true;
return builted(root[root[i].brother].child,str,k+1,n);
}
else continue;
return builted(root[i].brother,str,k,n);
}
int found(int pre,char str[],int k,int n)
{
if(k==n)return n-1;
if(pre==-1)
{//查找不成功就添加
return k-1;
}
if(root[pre].letter == str[k])
if(root[pre].repeated)return found(root[pre].child,str,k+1,n);
else return k;
int i;
for(i=pre;root[i].brother!=-1;i=root[i].brother)
if( root[root[i].brother].letter == str[k])
if(root[root[i].brother].repeated)
return found(root[root[i].brother].child,str,k+1,n);
else return k;
else continue;
return k;
}
int main()
{
int i,j,len,n,rt;
e=0;rt=0;
memset(root,-1,sizeof(root));
for(n=0;~scanf("%s",Letter[n].str);n++)
builted(rt,Letter[n].str,0,strlen(Letter[n].str));
for(i=0;i<n;i++)
{
printf("%s ",Letter[i].str);
len=found(rt,Letter[i].str,0,strlen(Letter[i].str));
for(j=0;j<=len;j++)
printf("%c",Letter[i].str[j]);
printf("\n");
}
return 0;
}