Trie字符串統計-java

Trie,又稱前綴樹或字典樹,是一種有序樹,用于保存關聯數組,其中的鍵通常是字符串。

目錄

前言?

一、Trie字符串統計?

二、算法思路?

1.Trie樹定義🌙

2.變量解釋🌙

3.插入操作🌙

4.Trie樹查找操作?🌙

三、代碼如下?

1.代碼如下:🌙

2.讀入數據🌙

3.代碼運行結果🌙

?4.運行結果解釋🌙

總結?


前言?

Trie,又稱前綴樹或字典樹,是一種有序樹,用于保存關聯數組,其中的鍵通常是字符串。


提示:以下是本篇文章正文內容,下面案例可供參考

一、Trie字符串統計?

維護一個字符串集合,支持兩種操作:

  1. I x?向集合中插入一個字符串?x;
  2. Q x?詢問一個字符串在集合中出現了多少次。

共有?N?個操作,所有輸入的字符串總長度不超過?100000,字符串僅包含小寫英文字母。

輸入格式

第一行包含整數?N,表示操作數。

接下來?N行,每行包含一個操作指令,指令為?I x?或?Q x?中的一種。

輸出格式

對于每個詢問指令?Q x,都要輸出一個整數作為結果,表示?x?在集合中出現的次數。

每個結果占一行。

數據范圍

1≤N≤2?10000

二、算法思路?

1.Trie樹定義🌙

圖1.1Trie樹示例?

?Trie,又稱前綴樹或字典樹,是一種有序樹,用于保存關聯數組,其中的鍵通常是字符串。

Trie樹是用來高效的存儲和查找字符串的集合的數據結構。

基本性質:

1、根節點不包含字符,除根節點意外每個節點只包含一個字符。

2、從根節點到某一個節點,路徑上經過的字符連接起來,為該節點對應的字符串。

3、每個節點的所有子節點包含的字符串不相同。

圖1.1中我們用trie樹存儲了abcdef、abdef、aced、bcdf、bcff、cdaa、bcdc字符串。

我們會在一個單詞的結尾來做一個標記,來表示到這里有一個完整的單詞。

2.變量解釋🌙

我們引入整型變量N為100010,用來表示樹深最高100000個結;然后有因為字符串中只有小寫字母,那么一個結點最多有26個分支,那么我們用一個二維整型數組son來存儲,共有N行26列;用一維整型數組cnt來存儲以某節點結束的字符串的個數,同時起到字符串結束的作用,引入一個整型變量index,初始化為0,用來表示空節點。

3.插入操作🌙

插入操作我們按照一個字符串的字母順序第一個字符是根節點的分支,然后下一個字母是上一個字母的分支,直到單詞的結束;遇到相同前綴的單詞在相同單詞的前綴后的不同分支接著串連字母,當然每個單詞的最后一個字母都會有一個結束標志。具體模擬過程可以看圖1.1.

圖3.1模擬過程

對于一個字符串str,獲取對應的字符數組arr,建立一個整型變量p初始化為0,相當于一個指針變量指向當前節點,我們遍歷每個字符arr[i]?,然后用u = arr[i] - 'a',將每個字符轉換成數字關系,當該字符未被放入Trie樹中時即(son[p][u] == 0),將son[p][u] = ++index;意思是當該節點不存在的時候,我們創建出來,然后數組中的值是下一個節點的位置;然后將當前節點的指針p指向下一個節點的位置即 p = son[p][u];當該字符串的所有字符遍歷結束后,將cnt[p]++;此時p的值就是當前節點的位置,還因為index的值是隨著我們沒新創建一個節點增加的,是唯一的,它可以用來表示字符串結束的標識。

    public static void insert(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//字符不在Trie樹中if(son[p][u] == 0){//創建一個節點,數組中的值為下一個節點的位置son[p][u] = ++index;}//使指針指向下一個節點的位置p = son[p][u];}//結束時標記,記錄以此節點為結尾的字符串的個數cnt[p]++;}

4.Trie樹查找操作?🌙

我們還用圖1.1來看,當我們查找字符串acf的時候。從root-> a -> c - > e,此時a的后面沒有f,就說明Trie樹中不存在acf字符串;當我們字符串cda的時候,從root - > c - > d - > a,但是字符a沒有單詞結束標志,那么說明Trie樹中同樣也沒有字符串cda。

我們傳入一個字符串str,然后利用對應的字符數組arr,建立一個整型變量p初始化為0,相當于一個指針變量指向當前節點,我們遍歷每個字符arr[i]?,然后用u = arr[i] - 'a',將每個字符轉換成數字關系,當我們發現該字符不在Trie樹中時即son[p][u] == 0,即該字符串不存在直接返回0即可;當該字符存在,那么就將p指針指向該節點的下一個節點位置 p = son[p][u],將該字符數組遍歷完畢后,最后返回該字符串的個數就是以最后一個節點的位置對應的cnt數組中的值即cnt[p]。

    public static int query(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//不存在if(son[p][u] == 0){return 0;}p = son[p][u];}//返回字符串出現的次數return cnt[p];}

三、代碼如下?

1.代碼如下:🌙


import java.io.*;
import java.util.*;public class Trie字符串統計 {static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//一個字符串最多100000個字符static int N = 100010;//存儲子節點后面的分支,因為只有小寫字母,故只有26個分支static int[][] son = new int[N][26];//存儲以某節點結束的字符串的個數,同時起到字符串結束的標志作用static int[] cnt = new int[N];//下標是0的點既是根節點static int index = 0;public static void main(String[] args) throws Exception {Scanner sc = new Scanner(br);int m = sc.nextInt();while (m-- > 0){String cmd = sc.next();String str = sc.next();if (cmd.equals("I")){insert(str);}else if (cmd.equals("Q")){pw.println(query(str));}}pw.flush();}public static void insert(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//字符不在Trie樹中if(son[p][u] == 0){//創建一個節點,數組中的值為下一個節點的位置son[p][u] = ++index;}//使指針指向下一個節點的位置p = son[p][u];}//結束時標記,記錄以此節點為結尾的字符串的個數cnt[p]++;}public static int query(String str){char[] arr = str.toCharArray();int p = 0;for(int i = 0;i < arr.length;i++){int u = arr[i] - 'a';//不存在if(son[p][u] == 0){return 0;}p = son[p][u];}//返回字符串出現的次數return cnt[p];}
}

2.讀入數據🌙

5
I abc
Q abc
Q ab
I ab
Q ab

3.代碼運行結果🌙

1
0
1

?4.運行結果解釋🌙

圖4.1?

插入abc后查詢abc為1;查詢ab不存在為0;?插入ab;查詢ab存在為1。


總結?

主要了解Trie樹的構造性質后,直到如何插入字符串,如何查詢字符串;了解代碼中各個變量的含義,直到每一步是干什么,可以跟著圖示自己手動模擬一下,體驗一下過程,加深自己的理解。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/18537.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/18537.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/18537.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vim文本編輯器相關用法

1. 引言 Vim&#xff0c;一個功能強大的文本編輯器&#xff0c;它在程序員和系統管理員中廣受歡迎。Vim是Vi的增強版&#xff0c;提供了一系列高級功能&#xff0c;包括語法高亮、代碼補全、多窗口編輯等。 2. Vim的安裝 Vim的安裝過程在不同的Linux發行版中略有不同。以下是…

MapStruct高級用法

MapStruct高級用法 依賴注入&#xff08;Using dependency injection&#xff09; Mapper(componentModel SPRING) public interface SpringMapper {SpringMapper MAPPER Mappers.getMapper(SpringMapper.class);PersonDTO personDoToDTO(Person person); }public static fin…

【class18】人工智能初步----語音識別(4)

【class17】 上節課&#xff0c;我們學習了: 語音端點檢測的相關概念&#xff0c;并通過代碼切分和保存了音頻。 本節課&#xff0c;我們將學習這些知識點&#xff1a;1. 序列到序列模型2. 循環神經網絡3. 調用短語音識別接口 知其然&#xff0c;知其所以然 在調用語…

數組單調棧-901. 股票價格跨度、leetcode

單調棧作為一種數據結構在求解類遞增、遞減方面的題目中有較為廣泛的應用&#xff0c;在以往的leetcode中所見到的相關單調棧的題目均為單一元素&#xff0c;今天刷到901題目時&#xff0c;想到了將數組元素作為單調棧中元素的方法進行求解。 題目鏈接及描述 901. 股票價格跨…

【c++leetcode】69. Sqrt(x)

問題入口 二分搜索 最困難的是能否意識到用二分搜索法解題。 算術平方根的區間在[1, x] 。代碼如下&#xff1a; class Solution { public:int mySqrt(int x) {if (x 1 || x 0){return x;}int64_t start 1;int64_t end x;while (start < x){int64_t mid start (en…

開源模型應用落地-Gradio正確集成Fastapi-助力模型交互-實踐篇(二)

一、前言 Gradio提供了直觀的用戶界面,當與Fastapi結合后,用戶可以通過界面輕松地與模型進行交互,上傳數據、獲取推理結果等,使得交互性增強,提升了用戶體驗。 在開源大語言模型遍地開花的時代,正確的使用Gradio和Fastapi,通過兩者的集成,使得模型的部署和使用過程更加…

以果決其行,只為文化的傳承

從他們每一個人的身上&#xff0c;我們看到傳神的東西&#xff0c;就是他們都能用結果&#xff0c;去指引自己前進的方向&#xff0c;這正是我要解讀倪海廈老師的原因&#xff0c;看倪海廈2012年已經去世&#xff0c;到現在已經十幾年時間了&#xff0c;但是我們看現在自學中醫…

【Pandas】深入解析`pd.to_sql()`函數

【Pandas】深入解析pd.to_sql()函數 &#x1f308; 歡迎蒞臨我的個人主頁&#x1f448;這里是我深耕Python編程、機器學習和自然語言處理&#xff08;NLP&#xff09;領域&#xff0c;并樂于分享知識與經驗的小天地&#xff01;&#x1f387; &#x1f393; 博主簡介&#xff1…

2024年第六屆中青杯數學建模競賽淺析

獲取比賽資料&#xff0c;請關注gzh“小何數模”&#xff01; 本次中青杯數學建模的賽題已正式出爐&#xff0c;無論是賽題難度還是認可度&#xff0c;該比賽都是僅次于數模國賽的獨一檔&#xff0c;可以用于國賽前的練手訓練。考慮到大家解題實屬不易&#xff0c;為了幫助大家…

JavaSE:StringBuilder和StringBuffer類

1、引言 在上一篇文章中&#xff0c;我們理解了字符串的常用方法&#xff0c;細心的同學大概已經發現&#xff0c;不管是將字符串中的字符轉變為大寫或小寫&#xff0c;或是完成字符串的替換&#xff0c;又或是去除空白字符等等&#xff0c;只要涉及到字符串的修改&#xff0c…

【PB案例學習筆記】-10 進度條使用

寫在前面 這是PB案例學習筆記系列文章的第10篇&#xff0c;該系列文章適合具有一定PB基礎的讀者。 通過一個個由淺入深的編程實戰案例學習&#xff0c;提高編程技巧&#xff0c;以保證小伙伴們能應付公司的各種開發需求。 文章中設計到的源碼&#xff0c;小凡都上傳到了gite…

Java用反射reflect來實例化對象: class.getDeclaredConstructor().newInstance()

Java用反射reflect來實例化對象: class.getDeclaredConstructor().newInstance() 從java9開始, class.newInstance()已過時, 被加上Deprecated強烈反對注解 SuppressWarnings("removal")CallerSensitiveDeprecated(since"9")public T newInstance()throws …

防止自動化攻擊的最佳實踐

防止自動化攻擊的最佳實踐 在當今的網絡安全環境中&#xff0c;保護用戶賬戶免受自動化攻擊已成為每個網站和應用程序的重要任務。攻擊者可以利用多種不同類型的自動化攻擊來嘗試破壞用戶賬戶。本文將詳細介紹常見的攻擊類型及其防御機制&#xff0c;幫助您更好地保護用戶賬戶…

C# ManualResetEvent的用法

在C#中&#xff0c;ManualResetEvent類是一個同步基元&#xff0c;用于控制多個線程的執行順序。下面是一些ManualResetEvent類的常見用法&#xff1a; 等待一個事件的發生&#xff1a;可以使用ManualResetEvent的WaitOne方法來等待事件的發生。當事件被觸發時&#xff0c;Wait…

adb 連接機頂盒命令

抓機頂盒日志的方法&#xff0c;使用此命令進行抓日志&#xff0c;個別無法抓日志的盒子可以使用此方法 1、安卓9.0版本查詢命令 ps -ef |grep com.cm.webos.iptv 2、安卓4.4版本查詢命令 ps |grep com.cm.webos.iptv 3、查詢順序&#xff1a;首先進入shell下進行操作 adb she…

C++青少年簡明教程:for循環語句

C青少年簡明教程&#xff1a;for循環語句 C的for循環語句是一種迭代控制語句&#xff0c;用于重復執行一段代碼。 語法格式&#xff1a; for(表達式1&#xff1b;表達式2&#xff1b;表達式3) 循環體 for循環語句執行流程圖&#xff1a; 不太好理解&#xff0c;請看下圖&am…

VSCode配置Lua5.4安裝

參考&#xff1a;VSCode 配置 Lua 開發環境(清晰明了)_lua vscode-CSDN博客 1.下載 Lua Binaries Download (sourceforge.net) 2.配置環境變量 解壓放到某文件夾&#xff1a; 環境變量&#xff1a; 3.VSCode安裝插件 4.配置 5.測試

Python | Leetcode Python題解之第116題填充每個節點的下一個右側節點指針

題目&#xff1a; 題解&#xff1a; class Solution:def connect(self, root: Node) -> Node:if not root:return root# 從根節點開始leftmost rootwhile leftmost.left:# 遍歷這一層節點組織成的鏈表&#xff0c;為下一層的節點更新 next 指針head leftmostwhile head:#…

快解析動態域名解析,實現外網訪問內網數據庫

今天跟大家分享一下如何借助快解析動態域名解析&#xff0c;在兩種特定網絡環境下&#xff0c;實現外網訪問內網mysql數據庫。 第1種網絡環境&#xff1a;路由器分配的是動態公網IP&#xff0c;且有路由器登錄管理權限。如何實現外網訪問內網mysql數據庫&#xff1f; 針對這種…

繼承與Object

一.繼承 Java語言的繼承&#xff1a;單繼承 1.類和類之間的關系 (1)組合關系 公司和員工&#xff0c;學校和學生 (2)繼承關系 學生和人 二.Object類 public class Object {private static native void registerNatives();static {registerNatives();} 1.finalize() 對象…