poj 2001 Shortest Prefixes
题意描述:给出n个字符串,对每一个串,找出唯一能标志它的最短前缀。
举例:
输入:
aab
abc
cca
输出
aab aa
abc ab
cca c
思路:用所有的串构建tire树,并且当树中边是某两串的公共字符的时候,需要标记。
这样在找最短前缀的时候,只需要扫描一遍tire树,没有遇到公共字符边就返回。
算法分析:
N<1000,每个字符串不超过20个字符。
于是建立tire树的空间复杂度:1000*20*26
时间复杂度:1000*20
#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;
}