題目鏈接: hdu 2846
解題大意: 給出單詞的詞典,然後有N次查詢
每次查詢是給出的字符串是詞典中多少個單詞的子串
解題思路: 將每個單詞的長度1到Tlen長度爲T的子串存進字典樹
如單詞abacab,只要存abacab,bacab,acab,cab,ab,b
如果所有的子串都存進去的話,查詢的結果會重複
樹中每個結點w值代表經過該結點的次數,同一個單詞的子串僅+1
查詢的時候最後一個字符結點的w值既是答案
代碼:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 10010
struct snode{
int flag,w;
int next[26]; //第一種寫法
}Tree[MAX*50];
char ch1[30],ch[30];
int Index;
void Insert(int Tlen,int k) //遍歷插入字典樹
{
int i,S=0,child;
for(i=1;i<=Tlen;i++)
{
child=ch[i-1]-'a';
if(Tree[S].next[child]==0) //結點不存在則建立新節點
{
Tree[Index].flag=k,Tree[Index].w=1;
Tree[S].next[child]=Index++;
}
else
{
if(Tree[Tree[S].next[child]].flag!=k) //不是同一單詞+1
{
Tree[Tree[S].next[child]].flag=k;
Tree[Tree[S].next[child]].w++;
}
}
S=Tree[S].next[child];
}
}
int Query(int Tlen) //遍歷查詢字典樹
{
int i,S=0,child;
for(i=1;i<=Tlen;i++)
{
child=ch[i-1]-'a';
if(Tree[S].next[child]!=0)
{
if(i==Tlen) //返回最後一個字符的w值
{
return Tree[Tree[S].next[child]].w;
}
S=Tree[S].next[child];
}
else
return 0;
}
}
int main()
{
int n,i,j,j1,TTlen;
Index=1;
memset(Tree,0,sizeof(Tree));
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",ch1);
TTlen=strlen(ch1);
for(j=0;ch1[j];j++)
{
for(j1=0;ch1[j1+j];j1++) //分別以1..Tlen開頭的子串
{
ch[j1]=ch1[j1+j];
}
ch[j1]='\0';
Insert(TTlen-j,i+1); //單詞的子串建樹
}
}
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",ch);
printf("%d\n",Query(strlen(ch))); //查詢
}
return 0;
}