給一些字串,問如果使用strcmp函式對這些字串兩兩比較,需要進行多少次字元比較。(strcmp函式在題目中已給出,如果字元相等,則還需要將該字元與』\0』進行比較)
鏈式字典樹我自己的叫法,網上大多數題解都把這種字典樹叫做左兒子,右兄弟的字典樹,但是這種叫法感覺會引起誤解。一開始我以為右兄弟是根的兄弟,後來才意識到右兄弟是左兒子的兄弟。
具體效果見下圖。
可以看到,這樣儲存只需要開節點個數大小的陣列就可以了,不需要再開乙個二維陣列,從而節省了大量空間。對於這道題來說,所需的陣列空間直接降了1.5個數量級,效果是非常明顯的。
至於鏈式字典樹的儲存方式,可以用鍊錶,也可以用陣列模擬鍊錶。這裡我選擇用陣列模擬鍊錶來避免指標操作。
上述**是鏈式字典樹增加節點的過程,由於鏈式字典樹本身的陣列無法記錄節點對應的字元資訊,所以需要增加乙個字元記錄陣列,也就是c。val用來記錄節點值,在本題中用來記錄訪問次數。nex對應上圖中的next,son對應上圖中的son1。v=sz++;
c[v]=st[i];
val[v]=0;
son[v]=0;
nex[v]=son[u];
son[u]=v;
通過鏈式字典樹解決了儲存空間的問題以後,本題就算解決一半了。另一半是統計比較次數。對於普通字元(除了』\0』以外),每次字元比較都會比較兩次,呼叫字元比較的次數就是val[u]值(u表示將字串插入字典樹過程中訪問的節點)。如果一直比較到結尾還沒有分出大小,那麼還會額外針對』\0』比較兩次,這時候就需要+cnt[u]。(u代表末尾節點)如果在比較過程中分出了大小,還需要再加1次,因為最後一次不相等的比較沒有計算。
最後將所有計算得到的值累加起來就是所求的總比較次數。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define up(i,l,h) for(int i=l;i#define down(i,h,l) for(int i=h-1;i>=l;i--)
#define w(a) while(a)
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 100010
#define mod 1000000009
#define eps 1e-10
using
namespace
std;
int ch[4000010];
int val[4000010],nex[4000010],son[4000010],cnt[4000010];
char c[4000010];
char st[1010];
int sz;
ll ans;
int getnum(char c) else
if(c>='a'&&c<='z') else
if(c>='a'&&c<='z')
}void insert()
}if(!v)
u=v;
ans+=val[u]*2;
val[u]++;
}if(cnt[u])
cnt[u]++;
}int main()
printf("case %d: %lld\n",ks++,ans);
}}/*
3abc
abcabc
*/
字典樹(strcmp()函式,uva 11732)
有點類似樹形dp,fa u 代表u節點的父節點,說val u 表示u這個節點有多少個字串走過,因此在這個節點的比較總次數 val u val u 1 val u val fa u val u 值得注意的是,在其他節點中val u val u 1 並不會重複計算,而val u val fa u val...
trie樹,兒子兄弟表示法 uva11732
題意 給出n個字串,進行兩兩比較,計算比較的次數。剛開始用指標寫,發現這樣寫儲存資訊的時候不好計算,於是學習劉汝佳的兒子兄弟表示,這樣建樹統計分差點的比較次數是非常方便。include include include includeusing namespace std const int maxn...
UVa11520字典序迴圈
本題思路比較簡單,由於要求字典序最小,因此從第乙個位置開始,每次從a開始試錯,如果可以滿足,則進行下一位。我使用了int型別進行儲存,事實證明比標準ac麻煩了。雖然很多時候字串要轉換為int型別便於處理,但這裡不需要,直接把每行當成乙個字串就夠了。類似於ac標準答案,我們可以定義乙個template...