題目鏈接: hdu 1671
題目大意: 給出幾串數組,是否存在一個串是另外一個串的前綴,是則輸出"YES"
解題思路: 每個字符爲單位建立一棵Trie樹
字符串結尾的結點用w標記,然後插入時判斷兩種情況:
每次插入時如果經過之前插入字符串的結尾,則之前插入的字符串必定是前綴
每次插入時如果插到結尾還在之前的結點中,則現在插入的字符串必定是前綴
字典樹的兩種寫法:
1.結點中包含next[ ],加快查找時間,但耗費大量的空間
2.結點中不包含next[ ],類似與建立有向圖利用pre[ ]遍歷,查找時間慢些,但省下很多空間
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10100
struct snode{
char ch1;
int next,w; //第二種寫法
}Tree[MAX*100];
char ch[20];
int pd,Index,pre[MAX*100];
void Add_edge(int a,char ch2,int len,int Tlen) //建立有向圖
{
Tree[Index].ch1=ch2,Tree[Index].next=pre[a];
if(len==Tlen)
Tree[Index].w=1;
pre[a]=Index++;
}
void DFS(int Star,int len,int Tlen,int kk) //DFS遍歷
{
int i;
if(len>Tlen||pd)
return ;
if(Tree[Star].w==1)
{
pd=1;
return ;
}
for(i=pre[Star];i!=-1;i=Tree[i].next)
{
if(Tree[i].ch1==ch[len-1]) //遍歷之前插入的點
{
if(Tree[i].w==1) //小對大
{
pd=1;
return ;
}
if(len==Tlen)
{
pd=1;
return ;
}
DFS(i,len+1,Tlen,kk);
return ;
}
}
if(Tree[Star].w&&i==-1&&kk!=1) //找到結尾結點
{
pd=1;
return;
}
Add_edge(Star,ch[len-1],len,Tlen);
DFS(Index-1,len+1,Tlen,kk);
}
int main()
{
int t,n,i;
scanf("%d",&t);
while(t--)
{
pd=0;
Index=1;
memset(pre,-1,sizeof(pre));
memset(Tree,0,sizeof(Tree));
Tree[0].ch1='\0';
Tree[0].next=-1;
Tree[0].w=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",ch);
if(!pd) //找到前綴則停止搜索
{
DFS(0,1,strlen(ch),i);
}
}
if(pd)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}