Trie 总结

Trie树 c++实现 Trie,又称单词查找树、前缀树,是一种多叉树结构。 与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符串。 阅读详情

TRIE is an interesting data-structure used mainly for manipulating with Words in a language. This word is got from the word retrieve. TRIE (pronounced as 'try') has a wide variety of applications in

  • Spell checking
  • Data compression
  • Computational biology
  • Routing table for IP addresses
  • Storing/Querying XML documents etc.,
We shall see how to construct a basic TRIE data structure in Java.


A TRIE tree would typically look like the following



The above TRIE is constructed by inserting the words ball, bat, doll, dork, do, dorm, send, sense. The markers are denoted on the Node using a red star( * ). We shall look into more about the TRIE data structure in depth in the  next post .


In this section we shall see how the insert() method on the TRIE data structure works. We shall take a specific case and analyze it with pictorial representation.

Before we begin, assume we already have an existing TRIE as shown below.


Lets see the steps on how to insert a word "bate". Any insertion would ideally be following the below algorithm.

  1. If the input string length is zero, then set the marker for the root node to be true.
  2. If the input string length is greater than zero, repeat steps 3 and 4 for each character
  3. If the character is present in the child node of the current node, set the current node point to the child node.
  4. If the character is not present in the child node, then insert a new node and set the current node to that newly inserted node.
  5. Set the marker flag to true when the end character is reached.
Now lets see how the word "bate" is getting inserted. Since the word "bate" is having length greater than zero, we can start inspecting each word.
  • See whether "b" is present in the current node's children (which is root). Yes its present, so set the current node to the child node which is having the character "b".
  • See whether "a" is present in the current node's children. Yes its present, so set the current node to the child node which is having the character "a".
  • See whether "t" is present in the current node's children. Yes its present, so set the current node to the child node which is having the character "t".
  • See whether "e" is present in the current node's children. No, its not present, so create a new node with character set to "e". Since "e" is the end of the word, set the marker flag to true.


The above picture shows how the word "bate" is inserted into the existing TRIE data structure. This example clearly shows how the insertion in a TRIE happens.


Consider the following TRIE as usual.


The search alogirthm involves the following steps
  1. For each character in the string, see if there is a child node with that character as the content.
  2. If that character does not exist, return false
  3. If that character exist, repeat step 1.
  4. Do the above steps until the end of string is reached. 
  5. When end of string is reached and if the marker of the current Node is set to true, return true, else return false.
Using the above algorithm, lets perform a search for the key "do".
  1. See whether "d" is present in the current node's children. Yes its present, so set the current node to child node which is having character "d".
  2. See whether "o" is present in the current node's children. Yes its present, so set the current node to child node which is having character "o".
  3. Since "o" is the end of the word, see whether marker is set to true or false. Marker is set to false which means that "do" is not registered as a word in the TRIE. So, return false.


Using the same algorithm, lets perform a search for the key "ball"
  1. See whether "b" is present in the current node's children. Yes its present, so set the current node to child node which is having character "b".
  2. See whether "a" is present in the current node's children. Yes its present, so set the current node to child node which is having character "a".
  3. See whether "l" is present in the current node's children. Yes its present, so set the current node to child node which is having character "l".
  4. See whether "l" is present in the current node's children. Yes its present, so set the current node to child node which is having character "l".
  5. Since "l" is the end of the word, see whether marker is set to true or false. Marker is set to true which means that "ball" is registered as a word in the TRIE. So, return true

Now that we've seen the basic operations on how to work with a TRIE, we shall now see the space and time complexities in order to get a real feel of how good a TRIE data structure is. Lets take the two important operations INSERT and SEARCH to measure the complexity.

INSERT operation first. Lets always take into account the worst case timing first and later convince ourselves of the practical timings. For every Node in the TRIE we had something called as Collection where the Collection can be either a Set or a List. If we choose Set, the order of whatever operation we perform over that will be in O(1) time, whereas if we use a LinkedList the number of comparisons at worst will be 26 (the number of alphabets). So for moving from one node to another, there will be at least 26 comparisons will be required at each step. 

Having these in mind, for inserting a word of length 'k' we need (k * 26) comparisons. By Applying the Big O notation it becomes O(k) which will be again O(1). Thus insert operations are performed in constant time irrespective of the length of the input string (this might look lik an understatement, but if we make the length of the input string a worst case maximum, this sentence holds true).

Same holds true for the search operation as well. The search operation exactly performs the way the insert does and its order is O(k*26) = O(1)


public class Trie {

	private TrieNode root;			// Root node in trie
	
	/**
	 * Constructor for Trie class
	 */
	public Trie(){
		root = new TrieNode((char) 0);
	}
	
	/**
	 * A method to insert a word into the trie
	 * @param word The word to be inserted
	 */
	public void insert(String word){
		TrieNode cur = root;
		for(int i=0; i<word.length(); i++){
			Map<Character, TrieNode> children = cur.getChildren();
			char c = word.charAt(i);
			if(children.containsKey(c)){	// If the character is in trie, continue searching
				cur = children.get(c);
			}else{								// Otherwise, create a new trie node
				TrieNode newNode = new TrieNode(c);
				children.put(c, newNode);
				cur = newNode;
			}
		}
		cur.setEnd(true);					// Markup for the end of word
	}
	
	/**
	 * A method used to determine if a word is stored in trie or not
	 * @param word The word to be checked
	 * @return	 True if the word is stored in trie, false otherwise
	 */
	public boolean contains(String word){
		TrieNode cur = root;
		for(int i=0; i<word.length(); i++){
			char c = word.charAt(i);
			if(!cur.children.containsKey(c)){		// Some letter is not in trie, return false
				return false;
			}
			cur = cur.children.get(c);
		}
		return cur.isEnd;								// When reaches the end of word, return value is based on if the markup is set or not
	}
	
	/**
	 * Inner class for Trie Node
	 * @author Bin Feng
	 *
	 */
	class TrieNode{
		private char letter;										// Letter associate with the node
		private Map<Character, TrieNode> children;		// Children of current node
		private boolean isEnd;								// Markup for end of word
		
		/**
		 * Constructor for TrieNode class
		 * @param letter The letter associate with node
		 */
		public TrieNode(char letter) {
			this.letter = letter;
			children = new HashMap<Character, Trie.TrieNode>();
			isEnd = false;
		}

		/**
		 * Getters and Setters
		 */
		public char getLetter() {
			return letter;
		}

		public void setLetter(char letter) {
			this.letter = letter;
		}

		public Map<Character, TrieNode> getChildren() {
			return children;
		}

		public void setChildren(Map<Character, TrieNode> children) {
			this.children = children;
		}

		public boolean isEnd() {
			return isEnd;
		}

		public void setEnd(boolean isEnd) {
			this.isEnd = isEnd;
		}

	}
}

http://www.technicalypto.com/2010/04/trie-in-java.html


// =====================================================================================================================

另一个完整版的Trie的实现,其中的search方法可用于解决如同:Google搜索找autocomplete字符串的问题。


TrieNode:

package Trie;

import java.util.HashMap;
import java.util.Map;

public class TrieNode<T> {
	private Character nodeKey;
	private T nodeValue;
	private boolean terminal;
	private Map<Character, TrieNode<T>> children = new HashMap<Character, TrieNode<T>>();

	public Character getNodeKey() {
		return nodeKey;
	}

	public void setNodeKey(Character nodeKey) {
		this.nodeKey = nodeKey;
	}

	public T getNodeValue() {
		return nodeValue;
	}

	public void setNodeValue(T nodeValue) {
		this.nodeValue = nodeValue;
	}

	public boolean isTerminal() {
		return terminal;
	}

	public void setTerminal(boolean terminal) {
		this.terminal = terminal;
	}

	public Map<Character, TrieNode<T>> getChildren() {
		return children;
	}

	public void setChildren(Map<Character, TrieNode<T>> children) {
		this.children = children;
	}
}


Trie:

package Trie;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Trie<T> {

	private TrieNode<T> rootNode = new TrieNode<T>();

	public void add(String key, T value) {
		addNode(rootNode, key, 0, value);
	}

	public T find(String key) {
		return findKey(rootNode, key);
	}

	public List<T> search(String prefix) {
		List<T> list = new ArrayList<T>();

		char[] ch = prefix.toCharArray();
		TrieNode<T> node = rootNode;
		for (int i = 0; i < ch.length; i++) {
			node = node.getChildren().get(ch[i]);
			if (node == null) {
				break;
			}
		}

		if (node != null) {
			getValuesFromNode(node, list);
		}

		return list;
	}

	public boolean contains(String key) {
		return hasKey(rootNode, key);
	}

	public Set<String> getAllKeys() {
		Set<String> keySet = new HashSet<String>();
		getKeysFromNode(rootNode, "", keySet);

		return keySet;
	}

	public int size() {
		return getAllKeys().size();
	}

	private void getValuesFromNode(TrieNode<T> currNode, List<T> valueList) {
		if (currNode.isTerminal()) {
			valueList.add(currNode.getNodeValue());
		}

		Map<Character, TrieNode<T>> children = currNode.getChildren();
		Iterator childIter = children.keySet().iterator();
		while (childIter.hasNext()) {
			Character ch = (Character) childIter.next();
			TrieNode<T> nextNode = children.get(ch);
			getValuesFromNode(nextNode, valueList);
		}
	}

	private void getKeysFromNode(TrieNode<T> currNode, String key, Set keySet) {
		if (currNode.isTerminal()) {
			keySet.add(key);
		}

		Map<Character, TrieNode<T>> children = currNode.getChildren();
		Iterator childIter = children.keySet().iterator();
		while (childIter.hasNext()) {
			Character ch = (Character) childIter.next();
			TrieNode<T> nextNode = children.get(ch);
			String s = key + nextNode.getNodeKey();
			getKeysFromNode(nextNode, s, keySet);
		}
	}

	private T findKey(TrieNode<T> currNode, String key) {
		Character c = key.charAt(0);
		if (currNode.getChildren().containsKey(c)) {
			TrieNode<T> nextNode = currNode.getChildren().get(c);
			if (key.length() == 1) {
				if (nextNode.isTerminal()) {
					return nextNode.getNodeValue();
				}
			} else {
				return findKey(nextNode, key.substring(1));
			}
		}

		return null;
	}

	private boolean hasKey(TrieNode<T> currNode, String key) {
		Character c = key.charAt(0);
		if (currNode.getChildren().containsKey(c)) {
			TrieNode<T> nextNode = currNode.getChildren().get(c);
			if (key.length() == 1) {
				if (nextNode.isTerminal()) {
					return true;
				}
			} else {
				return hasKey(nextNode, key.substring(1));
			}
		}

		return false;
	}

	private void addNode(TrieNode<T> currNode, String key, int pos, T value) {
		Character c = key.charAt(pos);
		TrieNode<T> nextNode = currNode.getChildren().get(c);

		if (nextNode == null) {
			nextNode = new TrieNode<T>();
			nextNode.setNodeKey(c);
			if (pos < key.length() - 1) {
				addNode(nextNode, key, pos + 1, value);
			} else {
				nextNode.setNodeValue(value);
				nextNode.setTerminal(true);
			}
			currNode.getChildren().put(c, nextNode);
		} else {
			if (pos < key.length() - 1) {
				addNode(nextNode, key, pos + 1, value);
			} else {
				nextNode.setNodeValue(value);
				nextNode.setTerminal(true);
			}
		}
	}
}


TrieTest:

package Trie;

import static org.junit.Assert.*;

import org.junit.Test;

public class TrieTest {

	Trie<Product> productTrie = new Trie<Product>();
    
    public void setUp() throws Exception {
        productTrie.add("ham", new Product(1, "ham"));
        productTrie.add("hammer", new Product(2, "hammer"));
        productTrie.add("hammock", new Product(3, "hammock"));
        productTrie.add("ipod", new Product(4, "ipod"));
        productTrie.add("iphone", new Product(5, "iphone"));
    }
     
    public void testAdd() {
        assertEquals(5, productTrie.size());
    }
     
    public void testFind() {
        assertNotNull(productTrie.find("ham"));
    }
     
    public void testSearch() {
        assertEquals(3, productTrie.search("ha").size());
    }
     
    public void testContains() {
        assertEquals(true, productTrie.contains("ipod"));
    }
     
    public void testGetAllKeys() {
        assertEquals(5, productTrie.getAllKeys().size());
    }
     
    class Product {
        private int productId;
        private String productDesc;
         
        public Product(int productId, String productDesc) {
            this.productId = productId;
            this.productDesc = productDesc;
        }
         
        public int getProductId() {
            return productId;
        }
        public void setProductId(int productId) {
            this.productId = productId;
        }
        public String getProductDesc() {
            return productDesc;
        }
        public void setProductDesc(String productDesc) {
            this.productDesc = productDesc;
        }
         
    }

}



http://stevedaskam.wordpress.com/2009/05/28/trie-structures/

http://stevedaskam.wordpress.com/2009/05/17/autocomplete-data-structures/









Trie树 Trie树 标签(空格分隔): 数据结构 算法知识文档 Trie树 应用: trie树常用于搜索提示。如当输入一个网址,可以自动搜索出可能的选择。当没有完全匹配的搜索结果,可以返回前缀最相似的可能。 给你一个字典,构建一个字典的Trie树,然后每次询问给出字符串s,查询字典中以s作为前缀的单词个数. 插入一个字符串,就是建树的过程,查询一个字符串是否存在. 解决应用二: ... 阅读详情

相关推荐

Trie与可持久化Trie

Trie,也称为字典树或前缀树,是一种用于高效存储和检索字符串的树形数据结构。它的主要特点是利用字符串的公共前缀来减少存储空间和提高查询效率。下面是对 Trie 的常见操作的介绍:插入(Insertion):将一个字符串插入到 Trie 中。从根节点开始,逐个字符检查字符串,并根据字符是否存在于当前节点的子节点中进行相应的操作。如果字符不存在,则创建一个新的节点并将其链接到当前节点的子节点上。删除(Deletion):从 Trie 中删除一个字符串。与插入操作类似,逐个字符检查字符串并找到对应的节点。

m0_66252872的博客 1184

Trie的java实现

package com.meituan.nlp.test; import java.util.HashMap; import java.util.Map; public class Trie { private TrieNode root; public Trie() { root = new TrieNode(); root.wordEnd = false; } publi

luoyexuge的专栏 1070

01Trie/可持久化01Trie学习笔记

01Trie是什么?它是一种较为特殊的权值线段树,可以解决一类与按位运算有关的问题。

Lolierl的博客 2024

01trie模板 (校内OJ)

#3827 The XOR Largest Pair( WOJ ) 描述 在给定的 N 个整数 A1,A2,…,AN 中选出两个进行异或运算,得到的结果最大是多少? 一道基础的 01串trie 只知道trie,根据二进制的性质,取反匹配,不难想到解法; 最后注意边加数边去最大匹配值;(有顺序地枚举) 这样效率 nlogn #include&amp;lt;bits/stdc++.h&amp;gt; using...

Jun 425

TRIE树在输入法分词的应用

TRIE树,即字典树,可以用于排序、保存大量字符串,在搜索引擎和防火墙中都有着重要的作用。本文使用字典树读取汉语拼音并进行匹配,成功实现了汉语拼音的划分。 先来看看TRIE树的结构: 树从root根节点出发,每个节点都有26个子节点(对应各个字母)。不难发现所有n长度的单词组合都在高度为n的TRIE树中。我们把从root节点出发,到某叶子(或节点)的字母组合称为一个单词。 1.定

u011477670的专栏 2626

前缀树进阶:压缩Trie与三向Trie的实现

本文旨在介绍前缀树的两种高级实现方式:压缩Trie和三向Trie。我们将探讨它们如何解决标准Trie结构的空间浪费问题,同时保持或改进其查询性能。内容涵盖原理讲解、实现细节、性能分析和实际应用。回顾标准Trie结构及其局限性介绍压缩Trie的原理和实现介绍三向Trie的原理和实现对比分析三种结构的性能特点提供实际应用案例和实现示例Trie(前缀树): 一种树形数据结构,用于高效存储和检索字符串集合压缩Trie: 通过合并单分支路径来减少节点数量的Trie变体三向Trie。

AI 算法实战派 1641

TrieMap 实现

最大问题是占空间,R = 256,插入百万数量级的key就 OutOfMemory了。在key的数目比较小的情况下,正如理论指出的一样,性能高于HashMap;但到了占内存比较多的时候由于影响系统整体运行,性能不如HashMap。 用HashMap而不是大小为256的数组作为link的时候,占内存少的多,几千万级的都不会OutOfMemory。仔细算一下 256-way Trie的一个N

binling的专栏 1839

具身智能端到端大模型VLA (Vision Language Action)

在语言为条件的机器人任务中,策略必须具备理解语言指令、视觉感知环境并生成适当动作的能力,这就需要VLA的。例如,在自动驾驶领域,传统的做法是将感知、预测、规划等步骤分开处理,而VLA则试图用一个统一的框架来替代这种分立的方法。另外,VLA的模型对于算力的需求很大,单片AI算力1000Tops的Thor大概率会延期发布,加上英伟达芯片的量产时间与成本挑战,以及在国内的应用情况,对车企而言是个大问题。以谷歌DeepMind推出的RT-2为例,该模型可以在新的物体、背景和环境中表现出显著改善的性能。

具身智能机器人 1万+

poj 2001(trie)

/** * poj 2001 * trie字典树 * 題意:给出n个单词(1<=n<=1000),求出每个单词的非公共前缀,如果没有,则输出自己。 */ import java.util.*; class Node { int num; Node[] child = new Node[26]; } public class Main { final int MAX = 1005

左手程序,右手写诗… 1018

VSCode玩转ESP-ADF音频开发:从环境搭建到成功播放MP3的避坑全流程

本文详细介绍了如何在VSCode环境下使用ESP-ADF框架进行ESP32音频开发,从环境搭建到成功播放MP3的全流程。重点解析了`IDF_PATH`和`ADF_PATH`的配置问题,以及如何解决`xTaskCreateRestrictedPinnedToCore`等常见编译错误,帮助开发者快速上手ESP-ADF音频开发。

weixin_42520909的博客 339

HFSS入门 - 传输线线路损耗和串扰仿真

下图中两相近传输线存在端口间的串扰,而同一根传输线存在线路损耗。 我们可用S21描述端口1到端口2的线路损耗(插损?),用S13描述近端串扰,S24描述远端串扰,串扰通常要求-20dB以下。 实验目的:传输线线路损耗和串扰仿真 具体步骤: 1.草图: 其中板厚Subh为1mm。其余参数具体值如下: 2.由草图作图: 其中介质板表面设为GND。 3.设置激励:先在第一根传输线相连的XZ平面上做一...

qq_37274411的博客 9156

深入双数组Trie(Double-Array Trie)

什么是Double Array Trie Double Array Trie是TRIE树的一种变形,它是在保证TRIE树检索速度的前提下,提高空间利用率而提出的一种数据结构,本质上是一个确定有限自动机(deterministic finite automaton,简称DFA)。 所谓的DFA就是一个能实现状态转移的自动机。对于一个给定的属于该自动机的状态和一个属于该自动机字母表Σ的字符,它

zhoubl668的专栏:远帆,梦之帆! 2万+

西门子PLC1200与CB1241模块的Modbus RTU从站配置全流程(附串口调试技巧)

本文详细介绍了西门子S7-1200 PLC与CB1241通信模块实现Modbus RTU从站配置的全流程,包括硬件接线规范、TIA Portal工程组态、通信指令编程及串口调试技巧。通过实战案例和常见错误处理方案,帮助工程师快速搭建稳定的工业通信系统,提升自动化设备的互联互通能力。

weixin_29165725的博客 325

Trie树的实现

一、定义:         Trie,又称字典树,是一种用于快速检索的二十六叉树结构。典型的空间换时间 二、结构图:            三、原理:        Trie把要查找的关键词看作一个字符序列,并根据构成关键词字符的先后顺序检索树结构;         特别地:和二叉查找树不同,在Trie树中,每个结点上并非存储一个元素。 四、性质:        0、利用串的公共

思考,思考,再思考~ 7101

jlink驱动安装

jlink驱动下载安装及keil识别

qq_43868701的博客 3万+

Python爬虫实战:逆向工程与异步处理攻克Pinterest无限滚动瀑布流

我们将从零开始,逐步分析其数据接口,构建一个功能完整的爬虫,并深入探讨反爬虫策略的应对、性能优化以及数据存储等高级主题。: 在实际爬取中,你需要先访问一次Pinterest主页,获取初始的Cookie和CSRF Token,然后再发起API请求。: Python爬虫,Pinterest,无限滚动,瀑布流,异步IO,httpx,逆向工程,API接口,动态内容,反爬虫。你会很快发现一些关键的请求模式。:页面初始加载有限内容,随着用户滚动,新的图片块通过AJAX动态加载,实现“永无止境”的浏览。

2201_76125261的博客 551

算法 {Trie字典树}

1

qq_66485519的博客 394

《Zephyr OS 入门与实战》第15章:LoRaWAN 集成

【代码】《Zephyr OS 入门与实战》第15章:LoRaWAN 集成。

2301_79143213的博客 608

Trie树;双数组trie树

将原来需要多个数组才能表示的Trie树,使用两个数组就可以存储下来,可以极大的减小空间复杂度。由于用base和check两个数组构成,又称为双数组字典树。具体来说就是使用两个数组base[]和check[]来维护Trie树,base[]负责记录状态,check[]用于检验状态转移的正确性,当check[i]为负值时,表示此状态为字符串的结束。

An_person的博客 819

Python 爬虫实战:抓取新闻网站上的新闻标题和内容

随着信息化的进展,新闻网站已经成为人们获取新闻和时事资讯的主要途径。许多新闻网站提供了丰富的内容,涵盖了社会、政治、科技、娱乐等多个领域。通过抓取新闻网站的内容,我们可以分析新闻的趋势,获取某一领域的最新动态,甚至为数据分析和机器学习提供数据支持。本文将详细介绍如何使用 Python 编写爬虫,抓取新闻网站上的新闻标题和内容。requests:发送 HTTP 请求,获取页面内容。:解析 HTML 页面并提取数据。Selenium:抓取动态加载的网页内容。新闻API。

2201_76125261的博客 3407

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Trie的实现

近期实现的一个数据结构,当做学习C++ 的小练习吧,零基础真的很痛苦。 (介绍内容为摘抄http://blog.youkuaiyun.com/nash_/article/details/8227610) Trie树(又叫字典树,前缀树,单词查找树,键树)是一种树形数据结构 Trie树的特点:根节点为空值,剩下每一个节点保存一个字母。知道这些就够了! 我们再来看看这棵树能干什么?如果从根

魏同学不会讲故事 1201

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

标准Trie、压缩Trie、后缀Trie

ref : https://dsqiu.iteye.com/blog/1705697 1.Trie导引 Trie树是一种基于树的数据结构,又称单词查找树、前缀树,是一种哈希树的变种。应用于字符串的统计与排序,经常被搜索引擎系统用于文本词频统计。用于存储字符串以便支持快速模式匹配,主要应用在信息检索中,Trie支持的主要查询操作是模式匹配和前缀匹配。Trie树可以看着是一个确定有限状态自...

weixin_30838921的博客 241

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Trie Tree的c++实现

Trie Tree的c++实现

manthink2005的专栏 2058

Trie树(压缩Trie树及Double-Array Trie)

 又称字典树或者前缀树,一种用于快速检索的多叉树结构;英文字母的Trie树为26叉树,数字的Trie树为10叉树;All the descendants of a node have a common prefix of the sequence associated with that node, and the root is associated with the empty sequen

Aiphis的博客 3624
上一篇: 面经&感想
下一篇: 论华人在美职场中的注意点
chiiis
博客等级 码龄14年 422粉丝 429原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值